1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 18:18:12 +00:00

LibGUI: Add GWidget::doubleclick_event().

Now double-clicking an item in a GTableView or GItemView will activate it.
This commit is contained in:
Andreas Kling 2019-03-25 01:42:15 +01:00
parent 43f9027968
commit 20f7d7ec67
11 changed files with 100 additions and 7 deletions

25
LibGUI/GElapsedTimer.cpp Normal file
View file

@ -0,0 +1,25 @@
#include <LibGUI/GElapsedTimer.h>
void GElapsedTimer::start()
{
gettimeofday(&m_start_time, nullptr);
}
inline void timersub(const struct timeval* a, const struct timeval* b, struct timeval* result)
{
result->tv_sec = a->tv_sec - b->tv_sec;
result->tv_usec = a->tv_usec - b->tv_usec;
if (result->tv_usec < 0) {
--result->tv_sec;
result->tv_usec += 1000000;
}
}
int GElapsedTimer::elapsed() const
{
struct timeval now;
gettimeofday(&now, nullptr);
struct timeval diff;
timersub(&now, &m_start_time, &diff);
return diff.tv_sec * 1000 + diff.tv_usec / 1000;
}

14
LibGUI/GElapsedTimer.h Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include <time.h>
class GElapsedTimer {
public:
GElapsedTimer() { }
void start();
int elapsed() const;
private:
struct timeval m_start_time { 0, 0 };
};

View file

@ -80,6 +80,16 @@ void GItemView::mousedown_event(GMouseEvent& event)
}
}
void GItemView::doubleclick_event(GMouseEvent& event)
{
if (!model())
return;
if (event.button() == GMouseButton::Left) {
mousedown_event(event);
model()->activate(model()->selected_index());
}
}
void GItemView::paint_event(GPaintEvent& event)
{
Painter painter(*this);

View file

@ -30,6 +30,7 @@ private:
virtual void resize_event(GResizeEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override;
virtual void doubleclick_event(GMouseEvent&) override;
int item_count() const;
Rect item_rect(int item_index) const;

View file

@ -292,3 +292,13 @@ void GTableView::set_column_hidden(int column, bool hidden)
}
m_column_visibility[column] = !hidden;
}
void GTableView::doubleclick_event(GMouseEvent& event)
{
if (!model())
return;
if (event.button() == GMouseButton::Left) {
mousedown_event(event);
model()->activate(model()->selected_index());
}
}

View file

@ -36,6 +36,7 @@ private:
virtual void did_update_model() override;
virtual void paint_event(GPaintEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void doubleclick_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override;
void paint_headers(Painter&);

View file

@ -71,7 +71,7 @@ void GWidget::event(GEvent& event)
set_focus(true);
return mousedown_event(static_cast<GMouseEvent&>(event));
case GEvent::MouseUp:
return mouseup_event(static_cast<GMouseEvent&>(event));
return handle_mouseup_event(static_cast<GMouseEvent&>(event));
case GEvent::Enter:
return enter_event(event);
case GEvent::Leave:
@ -144,6 +144,30 @@ void GWidget::handle_resize_event(GResizeEvent& event)
return resize_event(event);
}
void GWidget::handle_mouseup_event(GMouseEvent& event)
{
mouseup_event(event);
if (!rect().contains(event.position()))
return;
// It's a click.. but is it a doubleclick?
// FIXME: This needs improvement.
int elapsed_since_last_click = m_click_clock.elapsed();
if (elapsed_since_last_click < 250) {
doubleclick_event(event);
} else {
m_click_clock.start();
}
}
void GWidget::click_event(GMouseEvent&)
{
}
void GWidget::doubleclick_event(GMouseEvent&)
{
}
void GWidget::resize_event(GResizeEvent&)
{
}

View file

@ -1,7 +1,8 @@
#pragma once
#include "GEvent.h"
#include "GObject.h"
#include <LibGUI/GElapsedTimer.h>
#include <LibGUI/GEvent.h>
#include <LibGUI/GObject.h>
#include <SharedGraphics/Rect.h>
#include <SharedGraphics/Color.h>
#include <SharedGraphics/Font.h>
@ -43,6 +44,8 @@ public:
virtual void mousemove_event(GMouseEvent&);
virtual void mousedown_event(GMouseEvent&);
virtual void mouseup_event(GMouseEvent&);
virtual void click_event(GMouseEvent&);
virtual void doubleclick_event(GMouseEvent&);
virtual void focusin_event(GEvent&);
virtual void focusout_event(GEvent&);
virtual void enter_event(GEvent&);
@ -141,6 +144,7 @@ private:
void handle_paint_event(GPaintEvent&);
void handle_resize_event(GResizeEvent&);
void handle_mouseup_event(GMouseEvent&);
void do_layout();
void invalidate_layout();
@ -158,4 +162,6 @@ private:
bool m_fill_with_background_color { false };
bool m_visible { true };
GElapsedTimer m_click_clock;
};

View file

@ -156,12 +156,10 @@ void GWindow::event(GEvent& event)
Point local_point { mouse_event.x() - window_relative_rect.x(), mouse_event.y() - window_relative_rect.y() };
auto local_event = make<GMouseEvent>(event.type(), local_point, mouse_event.buttons(), mouse_event.button(), mouse_event.modifiers());
m_automatic_cursor_tracking_widget->event(*local_event);
if (mouse_event.buttons() == 0) {
if (mouse_event.buttons() == 0)
m_automatic_cursor_tracking_widget = nullptr;
return;
}
return;
}
if (!m_main_widget)
return;
if (m_main_widget) {

View file

@ -51,6 +51,7 @@ LIBGUI_OBJS = \
GAbstractView.o \
GItemView.o \
GIcon.o \
GElapsedTimer.o \
GWindow.o
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)

View file

@ -798,12 +798,15 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
if (process_ongoing_window_resize(event, event_window))
return;
HashTable<WSWindow*> windows_who_received_mouse_event_due_to_cursor_tracking;
for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) {
if (!window->global_cursor_tracking())
continue;
ASSERT(window->is_visible()); // Maybe this should be supported? Idk. Let's catch it and think about it later.
Point position { event.x() - window->rect().x(), event.y() - window->rect().y() };
auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button(), event.modifiers());
windows_who_received_mouse_event_due_to_cursor_tracking.set(window);
window->on_message(*local_event);
}
@ -849,7 +852,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
if (window.type() == WSWindowType::Normal && event.type() == WSMessage::MouseDown)
move_to_front_and_make_active(window);
event_window = &window;
if (!window.global_cursor_tracking()) {
if (!window.global_cursor_tracking() && !windows_who_received_mouse_event_due_to_cursor_tracking.contains(&window)) {
// FIXME: Should we just alter the coordinates of the existing MouseEvent and pass it through?
Point position { event.x() - window.rect().x(), event.y() - window.rect().y() };
auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button(), event.modifiers());