mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 20:28:11 +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:
parent
43f9027968
commit
20f7d7ec67
11 changed files with 100 additions and 7 deletions
25
LibGUI/GElapsedTimer.cpp
Normal file
25
LibGUI/GElapsedTimer.cpp
Normal 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
14
LibGUI/GElapsedTimer.h
Normal 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 };
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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&)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -156,10 +156,8 @@ 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)
|
||||
|
|
|
@ -51,6 +51,7 @@ LIBGUI_OBJS = \
|
|||
GAbstractView.o \
|
||||
GItemView.o \
|
||||
GIcon.o \
|
||||
GElapsedTimer.o \
|
||||
GWindow.o
|
||||
|
||||
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue