Skip to content

Commit

Permalink
WindowServer: Add special treatment for modal windows.
Browse files Browse the repository at this point in the history
While a WSClientConnection has a modal window showing, non-modal windows
belonging to that client are not sent any events.
  • Loading branch information
awesomekling committed Mar 18, 2019
1 parent 57ff293 commit 43304d2
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 17 deletions.
2 changes: 2 additions & 0 deletions AK/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ constexpr unsigned KB = 1024;
constexpr unsigned MB = KB * KB;
constexpr unsigned GB = KB * KB * KB;

enum class IterationDecision { Continue, Abort };

namespace std {
typedef decltype(nullptr) nullptr_t;
}
Expand Down
6 changes: 3 additions & 3 deletions Applications/IRCClient/IRCAppWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ void IRCAppWindow::setup_client()
};

m_client.on_connect = [this] {
GMessageBox box("We are connected!", "Message");
int code = box.exec();
dbgprintf("GMessageBox::exec() returned %d\n", code);
m_client.join_channel("#test");
};

Expand All @@ -62,6 +59,9 @@ void IRCAppWindow::setup_actions()

m_whois_action = GAction::create("Whois user", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-whois.rgb", { 16, 16 }), [] (auto&) {
printf("FIXME: Implement whois action\n");
GMessageBox box("Who would you like to WHOIS?", "Whois user");
int code = box.exec();
dbgprintf("GMessageBox::exec() returned %d\n", code);
});

m_open_query_action = GAction::create("Open query", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/irc-open-query.rgb", { 16, 16 }), [] (auto&) {
Expand Down
2 changes: 2 additions & 0 deletions LibGUI/GWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ void GWindow::show()
request.window_id = m_window_id;
request.window.rect = m_rect_when_windowless;
request.window.has_alpha_channel = m_has_alpha_channel;
request.window.modal = m_modal;
request.window.resizable = m_resizable;
request.window.opacity = m_opacity_when_windowless;
request.window.size_increment = m_size_increment;
request.window.base_size = m_base_size;
Expand Down
1 change: 1 addition & 0 deletions LibGUI/GWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,6 @@ class GWindow : public GObject {
bool m_has_alpha_channel { false };
bool m_double_buffering_enabled { true };
bool m_modal { false };
bool m_resizable { true };
};

8 changes: 2 additions & 6 deletions WindowServer/WSAPITypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
#include <SharedGraphics/Color.h>
#include <SharedGraphics/Rect.h>

// GUI system call API types.

struct WSAPI_WindowFlags { enum {
Visible = 1 << 0,
}; };

typedef unsigned WSAPI_Color;

struct WSAPI_Point {
Expand Down Expand Up @@ -186,6 +180,8 @@ struct WSAPI_ClientMessage {
struct {
WSAPI_Rect rect;
bool has_alpha_channel;
bool modal;
bool resizable;
float opacity;
WSAPI_Size base_size;
WSAPI_Size size_increment;
Expand Down
13 changes: 12 additions & 1 deletion WindowServer/WSClientConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,9 @@ void WSClientConnection::handle_request(WSAPIGetClipboardContentsRequest&)
void WSClientConnection::handle_request(WSAPICreateWindowRequest& request)
{
int window_id = m_next_window_id++;
auto window = make<WSWindow>(*this, window_id);
auto window = make<WSWindow>(*this, window_id, request.is_modal());
window->set_has_alpha_channel(request.has_alpha_channel());
window->set_resizable(request.is_resizable());
window->set_title(request.title());
window->set_rect(request.rect());
window->set_opacity(request.opacity());
Expand Down Expand Up @@ -531,3 +532,13 @@ void WSClientConnection::on_request(WSAPIClientRequest& request)
break;
}
}

bool WSClientConnection::is_showing_modal_window() const
{
for (auto& it : m_windows) {
auto& window = *it.value;
if (window.is_visible() && window.is_modal())
return true;
}
return false;
}
25 changes: 25 additions & 0 deletions WindowServer/WSClientConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class WSClientConnection final : public WSMessageReceiver {
int fd() const { return m_fd; }
pid_t pid() const { return m_pid; }

bool is_showing_modal_window() const;

template<typename Matching, typename Callback> void for_each_window_matching(Matching, Callback);
template<typename Callback> void for_each_window(Callback);

private:
virtual void on_message(WSMessage&) override;

Expand Down Expand Up @@ -74,3 +79,23 @@ class WSClientConnection final : public WSMessageReceiver {

RetainPtr<SharedBuffer> m_last_sent_clipboard_content;
};

template<typename Matching, typename Callback>
void WSClientConnection::for_each_window_matching(Matching matching, Callback callback)
{
for (auto& it : m_windows) {
if (matching(*it.value)) {
if (callback(*it.value) == IterationDecision::Abort)
return;
}
}
}

template<typename Callback>
void WSClientConnection::for_each_window(Callback callback)
{
for (auto& it : m_windows) {
if (callback(*it.value) == IterationDecision::Abort)
return;
}
}
8 changes: 7 additions & 1 deletion WindowServer/WSMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,12 +392,14 @@ class WSAPIGetWindowRectRequest final : public WSAPIClientRequest {

class WSAPICreateWindowRequest : public WSAPIClientRequest {
public:
WSAPICreateWindowRequest(int client_id, const Rect& rect, const String& title, bool has_alpha_channel, float opacity, const Size& base_size, const Size& size_increment)
WSAPICreateWindowRequest(int client_id, const Rect& rect, const String& title, bool has_alpha_channel, bool modal, bool resizable, float opacity, const Size& base_size, const Size& size_increment)
: WSAPIClientRequest(WSMessage::APICreateWindowRequest, client_id)
, m_rect(rect)
, m_title(title)
, m_opacity(opacity)
, m_has_alpha_channel(has_alpha_channel)
, m_modal(modal)
, m_resizable(resizable)
, m_size_increment(size_increment)
, m_base_size(base_size)
{
Expand All @@ -406,6 +408,8 @@ class WSAPICreateWindowRequest : public WSAPIClientRequest {
Rect rect() const { return m_rect; }
String title() const { return m_title; }
bool has_alpha_channel() const { return m_has_alpha_channel; }
bool is_modal() const { return m_modal; }
bool is_resizable() const { return m_resizable; }
float opacity() const { return m_opacity; }
Size size_increment() const { return m_size_increment; }
Size base_size() const { return m_base_size; }
Expand All @@ -415,6 +419,8 @@ class WSAPICreateWindowRequest : public WSAPIClientRequest {
String m_title;
float m_opacity { 0 };
bool m_has_alpha_channel { false };
bool m_modal { false };
bool m_resizable { false };
Size m_size_increment;
Size m_base_size;
};
Expand Down
2 changes: 1 addition & 1 deletion WindowServer/WSMessageLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess
break;
case WSAPI_ClientMessage::Type::CreateWindow:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length), message.window.has_alpha_channel, message.window.opacity, message.window.base_size, message.window.size_increment));
post_message(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length), message.window.has_alpha_channel, message.window.modal, message.window.resizable, message.window.opacity, message.window.base_size, message.window.size_increment));
break;
case WSAPI_ClientMessage::Type::DestroyWindow:
post_message(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id));
Expand Down
19 changes: 17 additions & 2 deletions WindowServer/WSWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ WSWindow::WSWindow(WSMessageReceiver& internal_owner, WSWindowType type)
WSWindowManager::the().add_window(*this);
}

WSWindow::WSWindow(WSClientConnection& client, int window_id)
WSWindow::WSWindow(WSClientConnection& client, int window_id, bool modal)
: m_client(&client)
, m_type(WSWindowType::Normal)
, m_modal(modal)
, m_window_id(window_id)
, m_icon(default_window_icon())
{
Expand Down Expand Up @@ -73,6 +74,9 @@ void WSWindow::on_message(WSMessage& message)
if (m_internal_owner)
return m_internal_owner->on_message(message);

if (is_blocked_by_modal_window())
return;

WSAPI_ServerMessage server_message;
server_message.window_id = window_id();

Expand Down Expand Up @@ -137,7 +141,6 @@ void WSWindow::on_message(WSMessage& message)
if (server_message.type == WSAPI_ServerMessage::Type::Invalid)
return;

ASSERT(m_client);
m_client->post_message(server_message);
}

Expand All @@ -154,6 +157,13 @@ void WSWindow::set_visible(bool b)
invalidate();
}

void WSWindow::set_resizable(bool resizable)
{
if (m_resizable == resizable)
return;
m_resizable = resizable;
}

void WSWindow::invalidate()
{
WSWindowManager::the().invalidate(*this);
Expand All @@ -163,3 +173,8 @@ bool WSWindow::is_active() const
{
return WSWindowManager::the().active_window() == this;
}

bool WSWindow::is_blocked_by_modal_window() const
{
return !is_modal() && client() && client()->is_showing_modal_window();
}
11 changes: 10 additions & 1 deletion WindowServer/WSWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ class WSMenu;

class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> {
public:
WSWindow(WSClientConnection&, int window_id);
WSWindow(WSClientConnection&, int window_id, bool modal);
WSWindow(WSMessageReceiver&, WSWindowType);
virtual ~WSWindow() override;

bool is_blocked_by_modal_window() const;

WSClientConnection* client() { return m_client; }
const WSClientConnection* client() const { return m_client; }

Expand All @@ -38,6 +40,11 @@ class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSW
bool is_visible() const { return m_visible; }
void set_visible(bool);

bool is_modal() const { return m_modal; }

bool is_resizable() const { return m_resizable; }
void set_resizable(bool);

Rect rect() const { return m_rect; }
void set_rect(const Rect&);
void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); }
Expand Down Expand Up @@ -106,6 +113,8 @@ class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSW
bool m_visible { true };
bool m_has_alpha_channel { false };
bool m_has_painted_since_last_resize { false };
bool m_modal { false };
bool m_resizable { false };
RetainPtr<GraphicsBitmap> m_backing_store;
RetainPtr<GraphicsBitmap> m_last_backing_store;
int m_window_id { -1 };
Expand Down
8 changes: 7 additions & 1 deletion WindowServer/WSWindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,14 +512,17 @@ void WSWindowManager::add_window(WSWindow& window)
{
m_windows.set(&window);
m_windows_in_order.append(&window);
if (!active_window())
if (!active_window() || active_window()->client() == window.client())
set_active_window(&window);
if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher)
m_switcher.refresh();
}

void WSWindowManager::move_to_front(WSWindow& window)
{
if (window.is_blocked_by_modal_window())
return;

if (m_windows_in_order.tail() != &window)
invalidate(window);
m_windows_in_order.remove(&window);
Expand Down Expand Up @@ -1095,6 +1098,9 @@ void WSWindowManager::set_highlight_window(WSWindow* window)

void WSWindowManager::set_active_window(WSWindow* window)
{
if (window && window->is_blocked_by_modal_window())
return;

if (window->type() != WSWindowType::Normal) {
dbgprintf("WSWindowManager: Attempted to make a non-normal window active.\n");
return;
Expand Down
1 change: 0 additions & 1 deletion WindowServer/WSWindowManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class WSWindowSwitcher;
class CharacterBitmap;
class GraphicsBitmap;

enum class IterationDecision { Continue, Abort };
enum class ResizeDirection { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft };

class WSWindowManager : public WSMessageReceiver {
Expand Down

0 comments on commit 43304d2

Please sign in to comment.