new feature: mouse support
This commit is contained in:
@@ -259,6 +259,47 @@ void Browser::SpacePressed()
|
||||
w->Scroll(wDown);
|
||||
}
|
||||
|
||||
void Browser::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
|
||||
return;
|
||||
if (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED)
|
||||
{
|
||||
w->Goto(me.y);
|
||||
switch (w->Current().type)
|
||||
{
|
||||
case itDirectory:
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
GetDirectory(w->Current().name);
|
||||
RedrawHeader = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t pos = w->GetPosition();
|
||||
SpacePressed();
|
||||
if (pos < w->Size()-1)
|
||||
w->Scroll(wUp);
|
||||
}
|
||||
break;
|
||||
case itPlaylist:
|
||||
case itSong:
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
size_t pos = w->GetPosition();
|
||||
SpacePressed();
|
||||
if (pos < w->Size()-1)
|
||||
w->Scroll(wUp);
|
||||
}
|
||||
else
|
||||
EnterPressed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
Screen< Menu<MPD::Item> >::MouseButtonPressed(me);
|
||||
}
|
||||
|
||||
MPD::Song *Browser::CurrentSong()
|
||||
{
|
||||
return !w->Empty() && w->Current().type == itSong ? w->Current().song : 0;
|
||||
|
||||
@@ -37,6 +37,7 @@ class Browser : public Screen< Menu<MPD::Item> >
|
||||
|
||||
virtual void EnterPressed();
|
||||
virtual void SpacePressed();
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual MPD::Song *CurrentSong();
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ class Clock : public Screen<Window>
|
||||
|
||||
virtual void EnterPressed() { }
|
||||
virtual void SpacePressed() { }
|
||||
virtual void MouseButtonPressed(MEVENT) { }
|
||||
|
||||
virtual bool allowsSelection() { return false; }
|
||||
|
||||
|
||||
@@ -327,6 +327,65 @@ void MediaLibrary::SpacePressed()
|
||||
AddToPlaylist(0);
|
||||
}
|
||||
|
||||
void MediaLibrary::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (!Artists->Empty() && Artists->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != Artists)
|
||||
{
|
||||
PrevColumn();
|
||||
PrevColumn();
|
||||
}
|
||||
if (size_t(me.y) < Artists->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
Artists->Goto(me.y);
|
||||
if (me.bstate & BUTTON3_PRESSED)
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
Albums->Clear(0);
|
||||
Songs->Clear(0);
|
||||
}
|
||||
else if (!Albums->Empty() && Albums->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != Albums)
|
||||
w == Artists ? NextColumn() : PrevColumn();
|
||||
if (size_t(me.y) < Albums->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
Albums->Goto(me.y);
|
||||
if (me.bstate & BUTTON3_PRESSED)
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
Songs->Clear(0);
|
||||
}
|
||||
else if (!Songs->Empty() && Songs->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != Songs)
|
||||
{
|
||||
NextColumn();
|
||||
NextColumn();
|
||||
}
|
||||
if (size_t(me.y) < Songs->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
Songs->Goto(me.y);
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
size_t pos = Songs->GetPosition();
|
||||
SpacePressed();
|
||||
if (pos < Songs->Size()-1)
|
||||
Songs->Scroll(wUp);
|
||||
}
|
||||
else
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
}
|
||||
}
|
||||
|
||||
MPD::Song *MediaLibrary::CurrentSong()
|
||||
{
|
||||
return w == Songs && !Songs->Empty() ? &Songs->Current() : 0;
|
||||
|
||||
@@ -48,6 +48,7 @@ class MediaLibrary : public Screen<Window>
|
||||
|
||||
virtual void EnterPressed() { AddToPlaylist(1); }
|
||||
virtual void SpacePressed();
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual MPD::Song *CurrentSong();
|
||||
|
||||
|
||||
16
src/menu.h
16
src/menu.h
@@ -118,6 +118,9 @@ namespace NCurses
|
||||
void IntoSeparator(size_t pos);
|
||||
void Swap(size_t one, size_t two);
|
||||
void Move(size_t from, size_t to);
|
||||
bool Goto(size_t y);
|
||||
|
||||
size_t GetPosition() const { return itsHighlight; }
|
||||
|
||||
bool isBold(int id = -1);
|
||||
void BoldOption(int index, bool bold);
|
||||
@@ -358,6 +361,19 @@ template <typename T> void NCurses::Menu<T>::Move(size_t from, size_t to)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> bool NCurses::Menu<T>::Goto(size_t y)
|
||||
{
|
||||
if (!itsOptionsPtr->at(itsBeginning+y) || itsOptionsPtr->at(itsBeginning+y)->isStatic)
|
||||
return false;
|
||||
size_t cur_pos = itsHighlight-itsBeginning;
|
||||
while (itsHighlight-itsBeginning != int(y) && (y < cur_pos || size_t(itsHighlight) < itsOptions.size()-1))
|
||||
{
|
||||
Scroll(y < cur_pos ? wUp : wDown);
|
||||
y < cur_pos ? cur_pos-- : cur_pos++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> void NCurses::Menu<T>::Refresh()
|
||||
{
|
||||
if (itsOptionsPtr->empty())
|
||||
|
||||
@@ -190,6 +190,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
gettimeofday(&now, 0);
|
||||
|
||||
MEVENT mouse_event;
|
||||
if (Config.mouse_support)
|
||||
{
|
||||
mousemask(ALL_MOUSE_EVENTS, 0);
|
||||
mouseinterval(0);
|
||||
}
|
||||
|
||||
while (!main_exit)
|
||||
{
|
||||
if (!Mpd->Connected())
|
||||
@@ -333,6 +340,45 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
myScreen->Scroll(wEnd);
|
||||
}
|
||||
else if (Config.mouse_support && input == KEY_MOUSE)
|
||||
{
|
||||
# ifdef USE_PDCURSES
|
||||
nc_getmouse(&mouse_event);
|
||||
# else
|
||||
getmouse(&mouse_event);
|
||||
# endif // USE_PDCURSES
|
||||
if (mouse_event.bstate & BUTTON1_PRESSED
|
||||
&& mouse_event.y == LINES-(Config.statusbar_visibility ? 2 : 1)
|
||||
) // progressbar
|
||||
{
|
||||
const Song *s = myPlaylist->NowPlayingSong();
|
||||
if (!s)
|
||||
continue;
|
||||
Mpd->Seek(s->GetTotalLength()*mouse_event.x/double(COLS));
|
||||
UpdateStatusImmediately = 1;
|
||||
}
|
||||
else if (mouse_event.bstate & BUTTON1_PRESSED
|
||||
&& Config.statusbar_visibility
|
||||
&& Mpd->GetState() > psStop
|
||||
&& mouse_event.y == LINES-1 && mouse_event.x < 9
|
||||
) // playing/paused
|
||||
{
|
||||
Mpd->Pause();
|
||||
UpdateStatusImmediately = 1;
|
||||
}
|
||||
else if ((mouse_event.bstate & BUTTON2_PRESSED || mouse_event.bstate & BUTTON4_PRESSED)
|
||||
&& Config.header_visibility
|
||||
&& mouse_event.y == 0 && size_t(mouse_event.x) > COLS-VolumeState.length()
|
||||
) // volume
|
||||
{
|
||||
if (mouse_event.bstate & BUTTON2_PRESSED)
|
||||
Mpd->SetVolume(Mpd->GetVolume()-2);
|
||||
else
|
||||
Mpd->SetVolume(Mpd->GetVolume()+2);
|
||||
}
|
||||
else
|
||||
myScreen->MouseButtonPressed(mouse_event);
|
||||
}
|
||||
else if (input == KEY_RESIZE)
|
||||
{
|
||||
# ifdef USE_PDCURSES
|
||||
|
||||
@@ -133,6 +133,20 @@ void Playlist::SpacePressed()
|
||||
w->Scroll(wDown);
|
||||
}
|
||||
|
||||
void Playlist::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
|
||||
return;
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
w->Goto(me.y);
|
||||
Mpd->Play(w->Current().GetPosition());
|
||||
UpdateStatusImmediately = 1;
|
||||
}
|
||||
else
|
||||
Screen< Menu<MPD::Song> >::MouseButtonPressed(me);
|
||||
}
|
||||
|
||||
MPD::Song *Playlist::CurrentSong()
|
||||
{
|
||||
return !w->Empty() ? &w->Current() : 0;
|
||||
|
||||
@@ -41,6 +41,7 @@ class Playlist : public Screen< Menu<MPD::Song> >
|
||||
|
||||
virtual void EnterPressed();
|
||||
virtual void SpacePressed();
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual MPD::Song *CurrentSong();
|
||||
|
||||
|
||||
@@ -281,6 +281,44 @@ void PlaylistEditor::SpacePressed()
|
||||
AddToPlaylist(0);
|
||||
}
|
||||
|
||||
void PlaylistEditor::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (!Playlists->Empty() && Playlists->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != Playlists)
|
||||
PrevColumn();
|
||||
if (size_t(me.y) < Playlists->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
Playlists->Goto(me.y);
|
||||
if (me.bstate & BUTTON3_PRESSED)
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
Content->Clear(0);
|
||||
}
|
||||
else if (!Content->Empty() && Content->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != Content)
|
||||
NextColumn();
|
||||
if (size_t(me.y) < Content->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
Content->Goto(me.y);
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
size_t pos = Content->GetPosition();
|
||||
SpacePressed();
|
||||
if (pos < Content->Size()-1)
|
||||
Content->Scroll(wUp);
|
||||
}
|
||||
else
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
}
|
||||
}
|
||||
|
||||
MPD::Song *PlaylistEditor::CurrentSong()
|
||||
{
|
||||
return w == Content && !Content->Empty() ? &Content->Current() : 0;
|
||||
|
||||
@@ -37,6 +37,7 @@ class PlaylistEditor : public Screen<Window>
|
||||
|
||||
virtual void EnterPressed() { AddToPlaylist(1); }
|
||||
virtual void SpacePressed();
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual MPD::Song *CurrentSong();
|
||||
|
||||
|
||||
31
src/screen.h
31
src/screen.h
@@ -49,6 +49,7 @@ class BasicScreen
|
||||
|
||||
virtual void EnterPressed() = 0;
|
||||
virtual void SpacePressed() = 0;
|
||||
virtual void MouseButtonPressed(MEVENT) { }
|
||||
|
||||
virtual MPD::Song *CurrentSong() { return 0; }
|
||||
|
||||
@@ -76,7 +77,9 @@ template <typename WindowType> class Screen : public BasicScreen
|
||||
virtual void Refresh();
|
||||
virtual void RefreshWindow();
|
||||
virtual void ReadKey(int &input);
|
||||
virtual void Scroll(Where where, const int *);
|
||||
virtual void Scroll(Where where, const int * = 0);
|
||||
|
||||
virtual void MouseButtonPressed(MEVENT me);
|
||||
|
||||
protected:
|
||||
WindowType *w;
|
||||
@@ -126,5 +129,31 @@ template <typename WindowType> void Screen<WindowType>::Scroll(Where where, cons
|
||||
w->Scroll(where);
|
||||
}
|
||||
|
||||
template <typename WindowType> void Screen<WindowType>::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (me.bstate & BUTTON2_PRESSED)
|
||||
{
|
||||
Scroll(wPageDown);
|
||||
}
|
||||
else if (me.bstate & BUTTON4_PRESSED)
|
||||
{
|
||||
Scroll(wPageUp);
|
||||
}
|
||||
}
|
||||
|
||||
template <> inline void Screen<Scrollpad>::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (me.bstate & BUTTON2_PRESSED)
|
||||
{
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
Scroll(wDown);
|
||||
}
|
||||
else if (me.bstate & BUTTON4_PRESSED)
|
||||
{
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
Scroll(wUp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -295,6 +295,34 @@ void SearchEngine::SpacePressed()
|
||||
w->Scroll(wDown);
|
||||
}
|
||||
|
||||
void SearchEngine::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
|
||||
return;
|
||||
if (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED)
|
||||
{
|
||||
if (!w->Goto(me.y))
|
||||
return;
|
||||
w->Refresh();
|
||||
if ((me.bstate & BUTTON3_PRESSED || w->GetPosition() > 10) && w->GetPosition() < StaticOptions)
|
||||
EnterPressed();
|
||||
else if (w->GetPosition() >= StaticOptions)
|
||||
{
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
size_t pos = w->GetPosition();
|
||||
SpacePressed();
|
||||
if (pos < w->Size()-1)
|
||||
w->Scroll(wUp);
|
||||
}
|
||||
else
|
||||
EnterPressed();
|
||||
}
|
||||
}
|
||||
else
|
||||
Screen< Menu< std::pair<Buffer *, MPD::Song *> > >::MouseButtonPressed(me);
|
||||
}
|
||||
|
||||
MPD::Song *SearchEngine::CurrentSong()
|
||||
{
|
||||
return !w->Empty() ? w->Current().second : 0;
|
||||
|
||||
@@ -48,6 +48,7 @@ class SearchEngine : public Screen< Menu< std::pair<Buffer *, MPD::Song *> > >
|
||||
|
||||
virtual void EnterPressed();
|
||||
virtual void SpacePressed();
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual MPD::Song *CurrentSong();
|
||||
|
||||
|
||||
@@ -280,6 +280,7 @@ void DefaultConfiguration(ncmpcpp_config &conf)
|
||||
conf.use_cyclic_scrolling = false;
|
||||
conf.allow_physical_files_deletion = false;
|
||||
conf.allow_physical_directories_deletion = false;
|
||||
conf.mouse_support = true;
|
||||
conf.set_window_title = true;
|
||||
conf.mpd_port = 6600;
|
||||
conf.mpd_connection_timeout = 15;
|
||||
@@ -679,6 +680,10 @@ void ReadConfiguration(ncmpcpp_config &conf)
|
||||
{
|
||||
conf.allow_physical_directories_deletion = v == "yes";
|
||||
}
|
||||
else if (cl.find("mouse_support") != string::npos)
|
||||
{
|
||||
conf.mouse_support = v == "yes";
|
||||
}
|
||||
else if (cl.find("enable_window_title") != string::npos)
|
||||
{
|
||||
conf.set_window_title = v == "yes";
|
||||
|
||||
@@ -172,6 +172,7 @@ struct ncmpcpp_config
|
||||
bool use_cyclic_scrolling;
|
||||
bool allow_physical_files_deletion;
|
||||
bool allow_physical_directories_deletion;
|
||||
bool mouse_support;
|
||||
|
||||
int mpd_port;
|
||||
int mpd_connection_timeout;
|
||||
|
||||
@@ -216,6 +216,21 @@ void TinyTagEditor::EnterPressed()
|
||||
UnlockStatusbar();
|
||||
}
|
||||
|
||||
void TinyTagEditor::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
|
||||
return;
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
{
|
||||
if (!w->Goto(me.y))
|
||||
return;
|
||||
w->Refresh();
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen< Menu<Buffer> >::MouseButtonPressed(me);
|
||||
}
|
||||
|
||||
bool TinyTagEditor::SetEdited(MPD::Song *s)
|
||||
{
|
||||
if (!s)
|
||||
@@ -728,6 +743,62 @@ void TagEditor::SpacePressed()
|
||||
Tags->Clear(0);
|
||||
}
|
||||
|
||||
void TagEditor::MouseButtonPressed(MEVENT me)
|
||||
{
|
||||
if (!LeftColumn->Empty() && LeftColumn->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != LeftColumn)
|
||||
{
|
||||
PrevColumn();
|
||||
PrevColumn();
|
||||
}
|
||||
if (size_t(me.y) < LeftColumn->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
LeftColumn->Goto(me.y);
|
||||
if (me.bstate & BUTTON1_PRESSED)
|
||||
EnterPressed();
|
||||
else
|
||||
SpacePressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
Tags->Clear(0);
|
||||
}
|
||||
else if (!TagTypes->Empty() && TagTypes->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != TagTypes)
|
||||
w == LeftColumn ? NextColumn() : PrevColumn();
|
||||
if (size_t(me.y) < TagTypes->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
if (!TagTypes->Goto(me.y))
|
||||
return;
|
||||
TagTypes->Refresh();
|
||||
Tags->Refresh();
|
||||
if (me.bstate & BUTTON3_PRESSED)
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
}
|
||||
else if (!Tags->Empty() && Tags->hasCoords(me.x, me.y))
|
||||
{
|
||||
if (w != Tags)
|
||||
{
|
||||
NextColumn();
|
||||
NextColumn();
|
||||
}
|
||||
if (size_t(me.y) < Tags->Size() && (me.bstate & BUTTON1_PRESSED || me.bstate & BUTTON3_PRESSED))
|
||||
{
|
||||
Tags->Goto(me.y);
|
||||
Tags->Refresh();
|
||||
if (me.bstate & BUTTON3_PRESSED)
|
||||
EnterPressed();
|
||||
}
|
||||
else
|
||||
Screen<Window>::MouseButtonPressed(me);
|
||||
}
|
||||
}
|
||||
|
||||
MPD::Song *TagEditor::CurrentSong()
|
||||
{
|
||||
return w == Tags && !Tags->Empty() ? &Tags->Current() : 0;
|
||||
|
||||
@@ -44,6 +44,7 @@ class TinyTagEditor : public Screen< Menu<Buffer> >
|
||||
|
||||
virtual void EnterPressed();
|
||||
virtual void SpacePressed() { }
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual bool allowsSelection() { return false; }
|
||||
|
||||
@@ -74,6 +75,7 @@ class TagEditor : public Screen<Window>
|
||||
|
||||
virtual void EnterPressed();
|
||||
virtual void SpacePressed();
|
||||
virtual void MouseButtonPressed(MEVENT);
|
||||
|
||||
virtual MPD::Song *CurrentSong();
|
||||
|
||||
|
||||
@@ -468,6 +468,8 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e
|
||||
switch (input)
|
||||
{
|
||||
case ERR:
|
||||
case KEY_MOUSE:
|
||||
break;
|
||||
case KEY_UP:
|
||||
if (itsHistory && !encrypted && history_offset > 0)
|
||||
{
|
||||
@@ -634,6 +636,11 @@ int Window::Y() const
|
||||
return itsY;
|
||||
}
|
||||
|
||||
bool Window::hasCoords(int &x, int &y)
|
||||
{
|
||||
return wmouse_trafo(itsWindow, &y, &x, 0);
|
||||
}
|
||||
|
||||
void Window::Scrollable(bool scrollable) const
|
||||
{
|
||||
scrollok(itsWindow, scrollable);
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace NCurses
|
||||
void GotoXY(int, int);
|
||||
int X() const;
|
||||
int Y() const;
|
||||
bool hasCoords(int &, int &);
|
||||
|
||||
void SetGetStringHelper(GetStringHelper helper) { itsGetStringHelper = helper; }
|
||||
void SetColor(Color, Color = clDefault);
|
||||
|
||||
Reference in New Issue
Block a user