mirror of
https://github.com/RGBCube/serenity
synced 2025-05-30 21:48:11 +00:00
Add WindowActivated and WindowDeactivated events.
Use this to implement different looking Terminal cursors depending on the window active state.
This commit is contained in:
parent
135ff48bb9
commit
dad58db757
9 changed files with 66 additions and 42 deletions
|
@ -63,6 +63,8 @@ struct GUI_Event {
|
||||||
MouseUp,
|
MouseUp,
|
||||||
KeyDown,
|
KeyDown,
|
||||||
KeyUp,
|
KeyUp,
|
||||||
|
WindowActivated,
|
||||||
|
WindowDeactivated,
|
||||||
};
|
};
|
||||||
Type type { Invalid };
|
Type type { Invalid };
|
||||||
int window_id { -1 };
|
int window_id { -1 };
|
||||||
|
|
|
@ -291,7 +291,8 @@ void Terminal::scroll_up()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
memset(&m_buffer[(m_rows - 1) * m_columns], ' ', m_columns);
|
memset(&m_buffer[(m_rows - 1) * m_columns], ' ', m_columns);
|
||||||
attribute_at(m_cursor_row, m_cursor_column).dirty = true;
|
// NOTE: We have to invalidate the cursor before memcpy()'ing the attributes.
|
||||||
|
invalidate_cursor();
|
||||||
memcpy(m_attributes, m_attributes + m_columns, m_columns * (m_rows - 1) * sizeof(Attribute));
|
memcpy(m_attributes, m_attributes + m_columns, m_columns * (m_rows - 1) * sizeof(Attribute));
|
||||||
for (size_t i = 0; i < m_columns; ++i)
|
for (size_t i = 0; i < m_columns; ++i)
|
||||||
m_attributes[((m_rows - 1) * m_columns) + i].reset();
|
m_attributes[((m_rows - 1) * m_columns) + i].reset();
|
||||||
|
@ -305,10 +306,10 @@ void Terminal::set_cursor(unsigned row, unsigned column)
|
||||||
{
|
{
|
||||||
ASSERT(row < rows());
|
ASSERT(row < rows());
|
||||||
ASSERT(column < columns());
|
ASSERT(column < columns());
|
||||||
attribute_at(m_cursor_row, m_cursor_column).dirty = true;
|
invalidate_cursor();
|
||||||
m_cursor_row = row;
|
m_cursor_row = row;
|
||||||
m_cursor_column = column;
|
m_cursor_column = column;
|
||||||
attribute_at(m_cursor_row, m_cursor_column).dirty = true;
|
invalidate_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::put_character_at(unsigned row, unsigned column, byte ch)
|
void Terminal::put_character_at(unsigned row, unsigned column, byte ch)
|
||||||
|
@ -449,7 +450,10 @@ void Terminal::paint()
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cursor_rect = glyph_rect(m_cursor_row, m_cursor_column);
|
auto cursor_rect = glyph_rect(m_cursor_row, m_cursor_column);
|
||||||
painter.draw_rect(cursor_rect, Color::MidGray);
|
if (m_in_active_window)
|
||||||
|
painter.fill_rect(cursor_rect, Color::MidGray);
|
||||||
|
else
|
||||||
|
painter.draw_rect(cursor_rect, Color::MidGray);
|
||||||
|
|
||||||
if (m_belling)
|
if (m_belling)
|
||||||
painter.draw_rect(rect, Color::Red);
|
painter.draw_rect(rect, Color::Red);
|
||||||
|
@ -460,3 +464,17 @@ void Terminal::paint()
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Terminal::set_in_active_window(bool b)
|
||||||
|
{
|
||||||
|
if (m_in_active_window == b)
|
||||||
|
return;
|
||||||
|
m_in_active_window = b;
|
||||||
|
invalidate_cursor();
|
||||||
|
paint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::invalidate_cursor()
|
||||||
|
{
|
||||||
|
attribute_at(m_cursor_row, m_cursor_column).dirty = true;
|
||||||
|
}
|
||||||
|
|
|
@ -17,11 +17,14 @@ public:
|
||||||
void paint();
|
void paint();
|
||||||
void on_char(byte);
|
void on_char(byte);
|
||||||
|
|
||||||
|
void set_in_active_window(bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Font& font() { return *m_font; }
|
Font& font() { return *m_font; }
|
||||||
void scroll_up();
|
void scroll_up();
|
||||||
void set_cursor(unsigned row, unsigned column);
|
void set_cursor(unsigned row, unsigned column);
|
||||||
void put_character_at(unsigned row, unsigned column, byte ch);
|
void put_character_at(unsigned row, unsigned column, byte ch);
|
||||||
|
void invalidate_cursor();
|
||||||
|
|
||||||
void escape$A(const Vector<unsigned>&);
|
void escape$A(const Vector<unsigned>&);
|
||||||
void escape$D(const Vector<unsigned>&);
|
void escape$D(const Vector<unsigned>&);
|
||||||
|
@ -94,5 +97,7 @@ private:
|
||||||
int m_line_spacing { 4 };
|
int m_line_spacing { 4 };
|
||||||
int m_line_height { 0 };
|
int m_line_height { 0 };
|
||||||
|
|
||||||
|
bool m_in_active_window { false };
|
||||||
|
|
||||||
RetainPtr<Font> m_font;
|
RetainPtr<Font> m_font;
|
||||||
};
|
};
|
||||||
|
|
|
@ -118,6 +118,8 @@ int main(int, char**)
|
||||||
case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
case GUI_Event::Type::KeyDown: dbgprintf("WID=%x KeyDown 0x%b (%c)\n", event.window_id, event.key.character, event.key.character); break;
|
case GUI_Event::Type::KeyDown: dbgprintf("WID=%x KeyDown 0x%b (%c)\n", event.window_id, event.key.character, event.key.character); break;
|
||||||
|
case GUI_Event::Type::WindowActivated: dbgprintf("WID=%x WindowActivated\n", event.window_id); break;
|
||||||
|
case GUI_Event::Type::WindowDeactivated: dbgprintf("WID=%x WindowDeactivated\n", event.window_id); break;
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -126,6 +128,10 @@ int main(int, char**)
|
||||||
terminal.paint();
|
terminal.paint();
|
||||||
} else if (event.type == GUI_Event::Type::KeyDown) {
|
} else if (event.type == GUI_Event::Type::KeyDown) {
|
||||||
write(ptm_fd, &event.key.character, 1);
|
write(ptm_fd, &event.key.character, 1);
|
||||||
|
} else if (event.type == GUI_Event::Type::WindowActivated) {
|
||||||
|
terminal.set_in_active_window(true);
|
||||||
|
} else if (event.type == GUI_Event::Type::WindowDeactivated) {
|
||||||
|
terminal.set_in_active_window(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,8 @@ int main(int argc, char** argv)
|
||||||
case GUI_Event::Type::MouseDown: dbgprintf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseDown: dbgprintf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
|
case GUI_Event::Type::WindowActivated: dbgprintf("WID=%x WindowActivated\n", event.window_id); break;
|
||||||
|
case GUI_Event::Type::WindowDeactivated: dbgprintf("WID=%x WindowDeactivated\n", event.window_id); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == GUI_Event::Type::MouseDown) {
|
if (event.type == GUI_Event::Type::MouseDown) {
|
||||||
|
|
|
@ -18,6 +18,8 @@ static const char* WSEvent_names[] = {
|
||||||
"Timer",
|
"Timer",
|
||||||
"WM_Compose",
|
"WM_Compose",
|
||||||
"WM_Invalidate",
|
"WM_Invalidate",
|
||||||
|
"WindowActivated",
|
||||||
|
"WindowDeactivated",
|
||||||
};
|
};
|
||||||
|
|
||||||
class WSEvent {
|
class WSEvent {
|
||||||
|
@ -35,6 +37,8 @@ public:
|
||||||
Timer,
|
Timer,
|
||||||
WM_Compose,
|
WM_Compose,
|
||||||
WM_Invalidate,
|
WM_Invalidate,
|
||||||
|
WindowActivated,
|
||||||
|
WindowDeactivated,
|
||||||
};
|
};
|
||||||
|
|
||||||
WSEvent() { }
|
WSEvent() { }
|
||||||
|
@ -67,22 +71,6 @@ private:
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShowEvent final : public WSEvent {
|
|
||||||
public:
|
|
||||||
ShowEvent()
|
|
||||||
: WSEvent(WSEvent::Show)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class HideEvent final : public WSEvent {
|
|
||||||
public:
|
|
||||||
HideEvent()
|
|
||||||
: WSEvent(WSEvent::Hide)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MouseButton : byte {
|
enum class MouseButton : byte {
|
||||||
None = 0,
|
None = 0,
|
||||||
Left,
|
Left,
|
||||||
|
@ -142,10 +130,3 @@ private:
|
||||||
Point m_position;
|
Point m_position;
|
||||||
MouseButton m_button { MouseButton::None };
|
MouseButton m_button { MouseButton::None };
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimerEvent final : public WSEvent {
|
|
||||||
public:
|
|
||||||
TimerEvent() : WSEvent(WSEvent::Timer) { }
|
|
||||||
~TimerEvent() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,12 @@ void WSWindow::event(WSEvent& event)
|
||||||
case WSEvent::WM_Invalidate:
|
case WSEvent::WM_Invalidate:
|
||||||
WSWindowManager::the().invalidate(*this);
|
WSWindowManager::the().invalidate(*this);
|
||||||
return;
|
return;
|
||||||
|
case WSEvent::WindowActivated:
|
||||||
|
gui_event.type = GUI_Event::Type::WindowActivated;
|
||||||
|
break;
|
||||||
|
case WSEvent::WindowDeactivated:
|
||||||
|
gui_event.type = GUI_Event::Type::WindowDeactivated;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gui_event.type == GUI_Event::Type::Invalid)
|
if (gui_event.type == GUI_Event::Type::Invalid)
|
||||||
|
|
|
@ -172,7 +172,7 @@ void WSWindowManager::addWindow(WSWindow& window)
|
||||||
m_windows.set(&window);
|
m_windows.set(&window);
|
||||||
m_windows_in_order.append(&window);
|
m_windows_in_order.append(&window);
|
||||||
if (!activeWindow())
|
if (!activeWindow())
|
||||||
setActiveWindow(&window);
|
set_active_window(&window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::move_to_front(WSWindow& window)
|
void WSWindowManager::move_to_front(WSWindow& window)
|
||||||
|
@ -192,7 +192,7 @@ void WSWindowManager::removeWindow(WSWindow& window)
|
||||||
m_windows.remove(&window);
|
m_windows.remove(&window);
|
||||||
m_windows_in_order.remove(&window);
|
m_windows_in_order.remove(&window);
|
||||||
if (!activeWindow() && !m_windows.is_empty())
|
if (!activeWindow() && !m_windows.is_empty())
|
||||||
setActiveWindow(*m_windows.begin());
|
set_active_window(*m_windows.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::notifyTitleChanged(WSWindow& window)
|
void WSWindowManager::notifyTitleChanged(WSWindow& window)
|
||||||
|
@ -253,7 +253,7 @@ void WSWindowManager::processMouseEvent(MouseEvent& event)
|
||||||
if (titleBarRectForWindow(window->rect()).contains(event.position())) {
|
if (titleBarRectForWindow(window->rect()).contains(event.position())) {
|
||||||
if (event.type() == WSEvent::MouseDown) {
|
if (event.type() == WSEvent::MouseDown) {
|
||||||
move_to_front(*window);
|
move_to_front(*window);
|
||||||
setActiveWindow(window);
|
set_active_window(window);
|
||||||
}
|
}
|
||||||
handleTitleBarMouseEvent(*window, event);
|
handleTitleBarMouseEvent(*window, event);
|
||||||
return;
|
return;
|
||||||
|
@ -262,7 +262,7 @@ void WSWindowManager::processMouseEvent(MouseEvent& event)
|
||||||
if (window->rect().contains(event.position())) {
|
if (window->rect().contains(event.position())) {
|
||||||
if (event.type() == WSEvent::MouseDown) {
|
if (event.type() == WSEvent::MouseDown) {
|
||||||
move_to_front(*window);
|
move_to_front(*window);
|
||||||
setActiveWindow(window);
|
set_active_window(window);
|
||||||
}
|
}
|
||||||
// FIXME: Re-use the existing event instead of crafting a new one?
|
// FIXME: Re-use the existing event instead of crafting a new one?
|
||||||
auto localEvent = make<MouseEvent>(event.type(), event.x() - window->rect().x(), event.y() - window->rect().y(), event.button());
|
auto localEvent = make<MouseEvent>(event.type(), event.x() - window->rect().x(), event.y() - window->rect().y(), event.button());
|
||||||
|
@ -342,8 +342,8 @@ void WSWindowManager::event(WSEvent& event)
|
||||||
|
|
||||||
if (event.isKeyEvent()) {
|
if (event.isKeyEvent()) {
|
||||||
// FIXME: This is a good place to hook key events globally. :)
|
// FIXME: This is a good place to hook key events globally. :)
|
||||||
if (m_activeWindow)
|
if (m_active_window)
|
||||||
return m_activeWindow->event(event);
|
return m_active_window->event(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,17 +354,21 @@ void WSWindowManager::event(WSEvent& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::setActiveWindow(WSWindow* window)
|
void WSWindowManager::set_active_window(WSWindow* window)
|
||||||
{
|
{
|
||||||
LOCKER(m_lock);
|
LOCKER(m_lock);
|
||||||
if (window == m_activeWindow.ptr())
|
if (window == m_active_window.ptr())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto* previously_active_window = m_activeWindow.ptr())
|
if (auto* previously_active_window = m_active_window.ptr()) {
|
||||||
|
WSEventLoop::the().post_event(previously_active_window, make<WSEvent>(WSEvent::WindowDeactivated));
|
||||||
invalidate(*previously_active_window);
|
invalidate(*previously_active_window);
|
||||||
m_activeWindow = window->makeWeakPtr();
|
}
|
||||||
if (m_activeWindow)
|
m_active_window = window->makeWeakPtr();
|
||||||
invalidate(*m_activeWindow);
|
if (m_active_window) {
|
||||||
|
WSEventLoop::the().post_event(m_active_window.ptr(), make<WSEvent>(WSEvent::WindowActivated));
|
||||||
|
invalidate(*m_active_window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::invalidate()
|
void WSWindowManager::invalidate()
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
void notifyTitleChanged(WSWindow&);
|
void notifyTitleChanged(WSWindow&);
|
||||||
void notifyRectChanged(WSWindow&, const Rect& oldRect, const Rect& newRect);
|
void notifyRectChanged(WSWindow&, const Rect& oldRect, const Rect& newRect);
|
||||||
|
|
||||||
WSWindow* activeWindow() { return m_activeWindow.ptr(); }
|
WSWindow* activeWindow() { return m_active_window.ptr(); }
|
||||||
|
|
||||||
void move_to_front(WSWindow&);
|
void move_to_front(WSWindow&);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ private:
|
||||||
void processMouseEvent(MouseEvent&);
|
void processMouseEvent(MouseEvent&);
|
||||||
void handleTitleBarMouseEvent(WSWindow&, MouseEvent&);
|
void handleTitleBarMouseEvent(WSWindow&, MouseEvent&);
|
||||||
|
|
||||||
void setActiveWindow(WSWindow*);
|
void set_active_window(WSWindow*);
|
||||||
|
|
||||||
virtual void event(WSEvent&) override;
|
virtual void event(WSEvent&) override;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ private:
|
||||||
HashTable<WSWindow*> m_windows;
|
HashTable<WSWindow*> m_windows;
|
||||||
InlineLinkedList<WSWindow> m_windows_in_order;
|
InlineLinkedList<WSWindow> m_windows_in_order;
|
||||||
|
|
||||||
WeakPtr<WSWindow> m_activeWindow;
|
WeakPtr<WSWindow> m_active_window;
|
||||||
|
|
||||||
WeakPtr<WSWindow> m_dragWindow;
|
WeakPtr<WSWindow> m_dragWindow;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue