Browse Source

Add WindowActivated and WindowDeactivated events.

Use this to implement different looking Terminal cursors depending on
the window active state.
Andreas Kling 6 years ago
parent
commit
dad58db757

+ 2 - 0
Kernel/GUITypes.h

@@ -63,6 +63,8 @@ struct GUI_Event {
         MouseUp,
         KeyDown,
         KeyUp,
+        WindowActivated,
+        WindowDeactivated,
     };
     Type type { Invalid };
     int window_id { -1 };

+ 22 - 4
Terminal/Terminal.cpp

@@ -291,7 +291,8 @@ void Terminal::scroll_up()
         }
 #endif
         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));
         for (size_t i = 0; i < m_columns; ++i)
             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(column < columns());
-    attribute_at(m_cursor_row, m_cursor_column).dirty = true;
+    invalidate_cursor();
     m_cursor_row = row;
     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)
@@ -449,7 +450,10 @@ void Terminal::paint()
     }
 
     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)
         painter.draw_rect(rect, Color::Red);
@@ -460,3 +464,17 @@ void Terminal::paint()
         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;
+}

+ 5 - 0
Terminal/Terminal.h

@@ -17,11 +17,14 @@ public:
     void paint();
     void on_char(byte);
 
+    void set_in_active_window(bool);
+
 private:
     Font& font() { return *m_font; }
     void scroll_up();
     void set_cursor(unsigned row, unsigned column);
     void put_character_at(unsigned row, unsigned column, byte ch);
+    void invalidate_cursor();
 
     void escape$A(const Vector<unsigned>&);
     void escape$D(const Vector<unsigned>&);
@@ -94,5 +97,7 @@ private:
     int m_line_spacing { 4 };
     int m_line_height { 0 };
 
+    bool m_in_active_window { false };
+
     RetainPtr<Font> m_font;
 };

+ 6 - 0
Terminal/main.cpp

@@ -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::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::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:
                 ASSERT_NOT_REACHED();
             }
@@ -126,6 +128,10 @@ int main(int, char**)
                 terminal.paint();
             } else if (event.type == GUI_Event::Type::KeyDown) {
                 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);
             }
         }
     }

+ 2 - 0
Userland/guitest.cpp

@@ -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::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::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) {

+ 4 - 23
WindowServer/WSEvent.h

@@ -18,6 +18,8 @@ static const char* WSEvent_names[] = {
     "Timer",
     "WM_Compose",
     "WM_Invalidate",
+    "WindowActivated",
+    "WindowDeactivated",
 };
 
 class WSEvent {
@@ -35,6 +37,8 @@ public:
         Timer,
         WM_Compose,
         WM_Invalidate,
+        WindowActivated,
+        WindowDeactivated,
     };
 
     WSEvent() { }
@@ -67,22 +71,6 @@ private:
     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 {
     None = 0,
     Left,
@@ -142,10 +130,3 @@ private:
     Point m_position;
     MouseButton m_button { MouseButton::None };
 };
-
-class TimerEvent final : public WSEvent {
-public:
-    TimerEvent() : WSEvent(WSEvent::Timer) { }
-    ~TimerEvent() { }
-};
-

+ 6 - 0
WindowServer/WSWindow.cpp

@@ -77,6 +77,12 @@ void WSWindow::event(WSEvent& event)
     case WSEvent::WM_Invalidate:
         WSWindowManager::the().invalidate(*this);
         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)

+ 16 - 12
WindowServer/WSWindowManager.cpp

@@ -172,7 +172,7 @@ void WSWindowManager::addWindow(WSWindow& window)
     m_windows.set(&window);
     m_windows_in_order.append(&window);
     if (!activeWindow())
-        setActiveWindow(&window);
+        set_active_window(&window);
 }
 
 void WSWindowManager::move_to_front(WSWindow& window)
@@ -192,7 +192,7 @@ void WSWindowManager::removeWindow(WSWindow& window)
     m_windows.remove(&window);
     m_windows_in_order.remove(&window);
     if (!activeWindow() && !m_windows.is_empty())
-        setActiveWindow(*m_windows.begin());
+        set_active_window(*m_windows.begin());
 }
 
 void WSWindowManager::notifyTitleChanged(WSWindow& window)
@@ -253,7 +253,7 @@ void WSWindowManager::processMouseEvent(MouseEvent& event)
         if (titleBarRectForWindow(window->rect()).contains(event.position())) {
             if (event.type() == WSEvent::MouseDown) {
                 move_to_front(*window);
-                setActiveWindow(window);
+                set_active_window(window);
             }
             handleTitleBarMouseEvent(*window, event);
             return;
@@ -262,7 +262,7 @@ void WSWindowManager::processMouseEvent(MouseEvent& event)
         if (window->rect().contains(event.position())) {
             if (event.type() == WSEvent::MouseDown) {
                 move_to_front(*window);
-                setActiveWindow(window);
+                set_active_window(window);
             }
             // 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());
@@ -342,8 +342,8 @@ void WSWindowManager::event(WSEvent& event)
 
     if (event.isKeyEvent()) {
         // FIXME: This is a good place to hook key events globally. :)
-        if (m_activeWindow)
-            return m_activeWindow->event(event);
+        if (m_active_window)
+            return m_active_window->event(event);
         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);
-    if (window == m_activeWindow.ptr())
+    if (window == m_active_window.ptr())
         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);
-    m_activeWindow = window->makeWeakPtr();
-    if (m_activeWindow)
-        invalidate(*m_activeWindow);
+    }
+    m_active_window = window->makeWeakPtr();
+    if (m_active_window) {
+        WSEventLoop::the().post_event(m_active_window.ptr(), make<WSEvent>(WSEvent::WindowActivated));
+        invalidate(*m_active_window);
+    }
 }
 
 void WSWindowManager::invalidate()

+ 3 - 3
WindowServer/WSWindowManager.h

@@ -25,7 +25,7 @@ public:
     void notifyTitleChanged(WSWindow&);
     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&);
 
@@ -45,7 +45,7 @@ private:
     void processMouseEvent(MouseEvent&);
     void handleTitleBarMouseEvent(WSWindow&, MouseEvent&);
 
-    void setActiveWindow(WSWindow*);
+    void set_active_window(WSWindow*);
     
     virtual void event(WSEvent&) override;
 
@@ -64,7 +64,7 @@ private:
     HashTable<WSWindow*> m_windows;
     InlineLinkedList<WSWindow> m_windows_in_order;
 
-    WeakPtr<WSWindow> m_activeWindow;
+    WeakPtr<WSWindow> m_active_window;
 
     WeakPtr<WSWindow> m_dragWindow;