From ecbc0322c11644ff186fe89fcd058c07a383a884 Mon Sep 17 00:00:00 2001 From: Jesse Buhagiar Date: Tue, 3 Sep 2019 21:45:02 +1000 Subject: [PATCH] Applications: Create a display properties manager An interactive application to modify the current display settings, such as the current wallpaper as well as the screen resolution. Currently we're adding the resolutions ourselves, because there's currently no way to detect was resolutions the current display adapter supports (or at least I can't see one... Maybe VBE does and I'm stupid). It even comes with a very nice template'd `ItemList` that can support a vector of any type, which makes life much simpler. --- .../DisplayProperties/DisplayProperties.cpp | 156 ++++++++++++++++++ .../DisplayProperties/DisplayProperties.h | 47 ++++++ .../DisplayProperties/ItemListModel.h | 54 ++++++ Applications/DisplayProperties/Makefile | 9 + Applications/DisplayProperties/main.cpp | 22 +++ .../icons/16x16/app-display-properties.png | Bin 0 -> 1617 bytes .../icons/32x32/app-display-properties.png | Bin 0 -> 2810 bytes Kernel/build-root-filesystem.sh | 1 + Kernel/makeall.sh | 1 + Libraries/LibGUI/GTabWidget.cpp | 2 +- Servers/WindowServer/WSAPITypes.h | 5 + Servers/WindowServer/WSClientConnection.cpp | 14 ++ Servers/WindowServer/WSClientConnection.h | 1 + Servers/WindowServer/WSCompositor.cpp | 2 + Servers/WindowServer/WSEvent.h | 16 ++ 15 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 Applications/DisplayProperties/DisplayProperties.cpp create mode 100644 Applications/DisplayProperties/DisplayProperties.h create mode 100644 Applications/DisplayProperties/ItemListModel.h create mode 100644 Applications/DisplayProperties/Makefile create mode 100644 Applications/DisplayProperties/main.cpp create mode 100644 Base/res/icons/16x16/app-display-properties.png create mode 100644 Base/res/icons/32x32/app-display-properties.png diff --git a/Applications/DisplayProperties/DisplayProperties.cpp b/Applications/DisplayProperties/DisplayProperties.cpp new file mode 100644 index 0000000000..74a1dacb7f --- /dev/null +++ b/Applications/DisplayProperties/DisplayProperties.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "DisplayProperties.h" +#include "ItemListModel.h" + +DisplayPropertiesWidget::DisplayPropertiesWidget() + : m_wm_config(CConfigFile::get_for_app("WindowManager")) +{ + create_root_widget(); + create_frame(); + create_resolution_list(); + create_wallpaper_list(); +} + +void DisplayPropertiesWidget::create_resolution_list() +{ + // TODO: Find a better way to get the default resolution + m_resolutions.append({ 640, 480 }); + m_resolutions.append({ 800, 600 }); + m_resolutions.append({ 1024, 768 }); + m_resolutions.append({ 1280, 1024 }); + m_resolutions.append({ 1366, 768 }); + m_resolutions.append({ 1440, 900 }); + m_resolutions.append({ 1600, 900 }); + m_resolutions.append({ 1920, 1080 }); + m_resolutions.append({ 2560, 1080 }); + + m_selected_resolution = m_resolutions.at(0); +} + +void DisplayPropertiesWidget::create_root_widget() +{ + m_root_widget = new GWidget; + m_root_widget->set_layout(make(Orientation::Vertical)); + m_root_widget->set_fill_with_background_color(true); + m_root_widget->layout()->set_margins({ 4, 4, 4, 16 }); +} + +void DisplayPropertiesWidget::create_wallpaper_list() +{ + CDirIterator iterator("/res/wallpapers/", CDirIterator::Flags::SkipDots); + + while (iterator.has_next()) + m_wallpapers.append(iterator.next_path()); +} + +void DisplayPropertiesWidget::create_frame() +{ + auto* tab_widget = new GTabWidget(m_root_widget); + + // First, let's create the "Background" tab + auto* background_splitter = new GSplitter(Orientation::Vertical, nullptr); + tab_widget->add_widget("Wallpaper", background_splitter); + + auto* background_content = new GWidget(background_splitter); + background_content->set_layout(make(Orientation::Vertical)); + background_content->layout()->add_spacer(); + background_content->layout()->set_margins({ 4, 4, 4, 4 }); + + auto* wallpaper_list = new GListView(background_content); + wallpaper_list->set_background_color(Color::White); + wallpaper_list->set_model(*ItemListModel::create(m_wallpapers)); + wallpaper_list->horizontal_scrollbar().set_visible(false); + wallpaper_list->on_selection = [this](auto& index) { + m_selected_wallpaper = m_wallpapers.at(index.row()); + }; + + // Let's add the settings tab + auto* settings_splitter = new GSplitter(Orientation::Vertical, nullptr); + tab_widget->add_widget("Settings", settings_splitter); + + auto* settings_content = new GWidget(settings_splitter); + settings_content->set_layout(make(Orientation::Vertical)); + settings_content->layout()->add_spacer(); + settings_content->layout()->set_margins({ 4, 4, 4, 4 }); + + auto* resolution_list = new GListView(settings_content); + resolution_list->set_background_color(Color::White); + resolution_list->set_model(*ItemListModel::create(m_resolutions)); + resolution_list->horizontal_scrollbar().set_visible(false); + resolution_list->on_selection = [this](auto& index) { + m_selected_resolution = m_resolutions.at(index.row()); + }; + + // Add the apply and cancel buttons + auto* bottom_widget = new GWidget(m_root_widget); + bottom_widget->set_layout(make(Orientation::Horizontal)); + bottom_widget->layout()->add_spacer(); + bottom_widget->set_size_policy(Orientation::Vertical, SizePolicy::Fixed); + bottom_widget->set_preferred_size(1, 22); + + auto* apply_button = new GButton(bottom_widget); + apply_button->set_text("Apply"); + apply_button->set_size_policy(Orientation::Vertical, SizePolicy::Fixed); + apply_button->set_size_policy(Orientation::Horizontal, SizePolicy::Fixed); + apply_button->set_preferred_size(60, 22); + apply_button->on_click = [this, tab_widget](GButton&) { + send_settings_to_window_server(tab_widget->get_active_tab()); + }; + + auto* ok_button = new GButton(bottom_widget); + ok_button->set_text("OK"); + ok_button->set_size_policy(Orientation::Vertical, SizePolicy::Fixed); + ok_button->set_size_policy(Orientation::Horizontal, SizePolicy::Fixed); + ok_button->set_preferred_size(60, 22); + ok_button->on_click = [this, tab_widget](GButton&) { + send_settings_to_window_server(tab_widget->get_active_tab()); + GApplication::the().quit(); + }; + + auto* cancel_button = new GButton(bottom_widget); + cancel_button->set_text("Cancel"); + cancel_button->set_size_policy(Orientation::Vertical, SizePolicy::Fixed); + cancel_button->set_size_policy(Orientation::Horizontal, SizePolicy::Fixed); + cancel_button->set_preferred_size(60, 22); + cancel_button->on_click = [this](GButton&) { + GApplication::the().quit(); + }; +} + +void DisplayPropertiesWidget::send_settings_to_window_server(int tab_index) +{ + if (tab_index == TabIndices::Wallpaper) { + StringBuilder builder; + builder.append("/res/wallpapers/"); + builder.append(m_selected_wallpaper); + GDesktop::the().set_wallpaper(builder.to_string()); + } else if (tab_index == TabIndices::Settings) { + WSAPI_ClientMessage request; + request.type = WSAPI_ClientMessage::Type::SetResolution; + dbg() << "Attempting to set resolution " << m_selected_resolution; + request.wm_conf.resolution = { m_selected_resolution.width(), m_selected_resolution.height() }; + auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetResolution); + ASSERT(response.value == 1); + } else { + dbg() << "Invalid tab index " << tab_index; + } +} diff --git a/Applications/DisplayProperties/DisplayProperties.h b/Applications/DisplayProperties/DisplayProperties.h new file mode 100644 index 0000000000..91fbc57609 --- /dev/null +++ b/Applications/DisplayProperties/DisplayProperties.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class DisplayPropertiesWidget final { +public: + enum class ButtonOperations { + Ok, + Apply, + Cancel, + }; + + enum TabIndices { + Wallpaper, + Settings + }; + +public: + DisplayPropertiesWidget(); + + // Apply the settings to the Window Server + void send_settings_to_window_server(int tabIndex); + void create_frame(); + + inline GWidget* get_root_widget() const { return m_root_widget; } + +private: + void create_wallpaper_list(); + void create_resolution_list(); + void create_root_widget(); + +private: + String m_wallpaper_path; + RefPtr m_wm_config; + GWidget* m_root_widget { nullptr }; + Vector m_resolutions; + Vector m_wallpapers; + + Size m_selected_resolution; + String m_selected_wallpaper; +}; diff --git a/Applications/DisplayProperties/ItemListModel.h b/Applications/DisplayProperties/ItemListModel.h new file mode 100644 index 0000000000..ea92a43a42 --- /dev/null +++ b/Applications/DisplayProperties/ItemListModel.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include + +template +class ItemListModel final : public GModel { +public: + static NonnullRefPtr create(Vector& data) { return adopt(*new ItemListModel(data)); } + + virtual ~ItemListModel() override {} + + virtual int row_count(const GModelIndex&) const override + { + return m_data.size(); + } + + virtual int column_count(const GModelIndex&) const override + { + return 1; + } + + virtual String column_name(int) const override + { + return "Data"; + } + + virtual ColumnMetadata column_metadata(int) const override + { + return { 70, TextAlignment::CenterLeft }; + } + + virtual GVariant data(const GModelIndex& index, Role role = Role::Display) const override + { + if (role == Role::Display) + return m_data.at(index.row()); + + return {}; + } + + virtual void update() override + { + did_update(); + } + +private: + explicit ItemListModel(Vector& data) + : m_data(data) + { + } + + Vector& m_data; +}; diff --git a/Applications/DisplayProperties/Makefile b/Applications/DisplayProperties/Makefile new file mode 100644 index 0000000000..a3d7d9462b --- /dev/null +++ b/Applications/DisplayProperties/Makefile @@ -0,0 +1,9 @@ +include ../../Makefile.common + +OBJS = \ + DisplayProperties.o \ + main.o \ + +APP = DisplayProperties + +include ../Makefile.common diff --git a/Applications/DisplayProperties/main.cpp b/Applications/DisplayProperties/main.cpp new file mode 100644 index 0000000000..5e0148c805 --- /dev/null +++ b/Applications/DisplayProperties/main.cpp @@ -0,0 +1,22 @@ +#include "DisplayProperties.h" +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + GApplication app(argc, argv); + DisplayPropertiesWidget instance; + + auto* window = new GWindow(); + window->set_title("Display Properties"); + window->resize(400, 448); + window->set_resizable(false); + window->set_main_widget(instance.get_root_widget()); + window->set_icon(load_png("/res/icons/16x16/app-display-properties.png")); + + window->show(); + return app.exec(); +} diff --git a/Base/res/icons/16x16/app-display-properties.png b/Base/res/icons/16x16/app-display-properties.png new file mode 100644 index 0000000000000000000000000000000000000000..6564dabede09e803436ae5d6e80572d735c3095c GIT binary patch literal 1617 zcmV-X2Cn&uP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+Rc_*vg$YtMgKL59)czLIUGN$?hJbPy&dO3cwIQa zM<+$>2uI%DOEFOY_s^hza0pu=>q7L&dxOI!nAG~D_}=IG&-fv4V;f2QtnJ=?Jo z{VdC0`LxH`-S=;E>8Ob1G_xEPS#N?l9!LL1i(~Y)x@0Q9(`-mXj9V=1p@xOcpV7V~i9=GBCb8={oT4d68(0S?0_pp1guCne_!3lia*w z6oBy9J$0MEOsg^1#{{b&=r)@p7MM+0DT?EBZRy5YjUx=TX1y;Q+MWOwVQvR8tRP@K z3Y$HfAQG72V+5ZJ<$|&=Ai$2CG^iA->H#OpoEy&s-o}cP6~^`g5KcW_k~m)-z_Qj^ zkM}L2gfcmG);Z^0aM2}~y?X1N_dfW!PvxM&1{Zt?A%+xk)M%rNK86@$iaAMAY-5g+ zPa(yWQqGt(+l*Wp<1+$9iWXa3@gH-fvrA9vQh4yb!Ur&r?&Cu_8G%~Lhk6P-m^`6#C zjdUyWJ&klOi+!qH!-%0D6FvK$e!qzOYoO1KURvp~*xwmX&qcqcnO+zF7ZA`)-!OV= zrcW#SL1n*R4D@M5-&FQPqhHiW-+_;%y|G!})kv?xK5c#vc2xRg%Rl->zu)G+=F!tc z?`nC&qoH|rq*T^{e_V~%%p=4>?e^#FLfV60=&L8#(3&Dw{M+2Z=2@$)^xN82dMp-N z?`nH)wkt1+x)E8E&@+GWM=#NT2|Fs`!rnq70004nX+uL$Nkc;*aB^>EX>4Tx0C=2z zkv&MmKpe$i)0V1K9PA+CkfAz=1@Q|~S<%#pCy1k}rc=I*5I_d9-xTnf21z{oL=GBn7JAN&t~ zcWdRx$K0fF90l3 z54hX``koBglpV=WQ^@Cm_cQvYEYN!kbgjC*HTQA)0Hmp_boz6+Axy+*`1ip9g+>NM8NeiPfZ^W<2L>jA1LPTi zYzWx~zzm_t0IY^mY5)sz+%BE|ocwfvE zaB^>EX>4U6ba`-PAZ2)IW&i+q+O=3~n(HbK{Ld<83A}`0IlT0JvxB?*DS?wXX`fEI z=iH<_wiOVfsw5z0{_|fk|G_Kx98Dz7sib7_iX|3bag*(S?W?nKeXf^3zQXg9-Q2(M zFa=!0eoXUdUty<52abomJ=+cU!%sdO9beoW1|3;P8%L0bqu{sQ9nYp5A=Px6&hanZ z7d27aU%fs@1{j0jFL>i;aKWxmzefs)B9u^Z-Jj8`g>X-}R{i!Xe&!C{1%UUv7yN8L z?BM~&c66Iodco&SO`TNNJ98v4G+4Jj+pNuRr_v~s+25_ZgQn#tBJ2Zro z7*@B0H{+jh&+A?A&bHbP)&{29494uPI1j|dMK@e^;^w+`*AZg$(=)E#cORB52lmDH zMM~7S6VC?BjF7=q2Xg^te~-njaf^}b!K1e>r06ZV2~Ef8569wZ5NH)LtA0-94r|$jdtgY<8e3u zL>QY8j0<4ECJ5UlXW4sp4mf7;QxUm`>>C(xWXKOh>0<~9| zAq56CNF9(BBgKS#%aBkt6eto=BBo4*Y6>YPN-1&DI#oGvWa7lknG4q(a?F%d=A3iM zwfGWH#>kXZxa3kwtr)b%3SSlND-6xI&|;&O8n@g^s~z&`u~Sc-d+w#z;YS!K0cNDZ zBabrbbQ4mVanekaXP#wNfz~8Q6p|z?S&Gy#Rn4tc|=J{&Tz^Y7>v_-5_jkB!Q3BtGeGyJ zy!k8Uj8gYEm@`V@fs0DxxiyqVJnCOP4h-yY=0SX34jwt{+1;PdlPkkqlU@a_IkZ0y9 zW!`Rh`lt>HlW4Jnl@i>Va)VJ^)}noZ<3})>OB~NAeh8xZ7|l0enpZS8K4g3T13U{H z?3^F)EOg9YfMh8ZZ?%bXtIq zN1=6-Mr>I1fWgh8H(2gxw%OdvH>ws%=tnlMn<94TWIKkE1_cu~56;~w*^*uNIEx%N zzrSuy&3o~GrhW6v8uEo&^Te$(kq-^hIk!)#U7O@EvAKIzh53l}aMSpMb(t~h0y0^! zIU54{c@2UBpMvV+HNq>=TxiDpN;DUmF)yN7lED`EESh$j7=_?9;~VlGONAFL1z5(K zVXPuOQAC7Z$!0k|JWw{di9tD9&qjw5Q(NRV(fH=5RHG6=i!iiWDERg=35L2Bo{ zn7I``wm?!FM1U1+r8%%iVawhLW$`WrF~eP%$F54uT#Ud>bB_GO>{@z z4xE;c?Eg{PuGQ@eisl4kT|$-gtJTfazp(i0Hq|hxBVz3Dea110j+&zfBMW_N-6*IV zGcKf&ekeMnEFrGKx#ZZ3S#q3^u188_9G;0K?84M`0&9y`e>j{?1!QN6QfpSiG>=jh z>LRx^{hf*jN$-!Mxbh_}wN-_upm2Ab^X}o9r}&W1bLEwWr$1#~2KXA@3eKFOdk*eh zXm#^;3(Z_ZcZr;>v+Rl!b4`q8hS^y!XZ+p zNb4Bhe2FOjI7hBx5p6$j5L$Ps&fsuVb5rQlL@fGqtvJ-9cicw{V_S?UvE3s3cB
J39fgoYA7L77opi!MU6=7ncM20 zCf9f*XdToMi8&^`e|PYWa=(QOMDh(jx5?WF@WKrh%VE^@GsW&|!q6XB=wxgt(f4!g zXqvvxo{qNHCi7Xd_a^hOi3hh|;>+LKHq8TAoPI#~=*o4B_lM)BD^}<7gHgs5Oi10C4=2nHSSM(r= z5aJk;n5oZ+VhWz)>mEM7-o<#9_qjhupOQBj;1h^vnQmCb8^qI_md<&fIKoPjLVQj< zZqNmZAGt2O{KmQHu%Bl}j7)l-I6^EGJ6P^uRx(uLDdMQ2YLxHKx~y>C;;dF`taVTR z!f;+&S>`&;5hSsQC5R9pqlPjnun?nFBgI6T_7fidVaG3$OD0ztj2sK7LWSh`!T;cQ zw`O5-!c7V%fY6I=e~bcMyFjyU+uz5w-8=yT&%l+|_E#Ig%qQvfwiZ1C`nQ3L>$WEE z0hc?#;FB&Hk|PCZ`U?f%{fxdT2MpW-y=!i7t$mz602%5kbpsq60%JwWUiWx+cV}<^ zo@w>>14`R+mvQQ*sQ>@~24YJ`L;(K)0000pCw%h&000SaNLh0L04^f{04^f|c%?sf z00007bV*G`2jd9@1v3;j3`Gn8009h*mNbM2QX8{Ia0$Nyrq#`1Gf^m#4k#KWJ`0(@Rj1R!GAOJvF-X1=TTbrWs9f4r! zMOC$`hT=Hn15{NDE{jwFsHkTljJENvN#538To%nnRlNqx=?-0!yw+9yJql|G;RRp_ z;SHdN@Cv|!JOKUzfQnkw`BVU?s70O8Wf2P^;CLa40M~(l?pF%v~waTB3k`EvKxzY003MNB%)o45S4U(=M>;VsC#*6+Zm_k3HCy2S+|i6VE_OC M07*qoM6N<$f`S_=uK)l5 literal 0 HcmV?d00001 diff --git a/Kernel/build-root-filesystem.sh b/Kernel/build-root-filesystem.sh index 8979c047e5..52a007ff15 100755 --- a/Kernel/build-root-filesystem.sh +++ b/Kernel/build-root-filesystem.sh @@ -86,6 +86,7 @@ cp ../Applications/SystemDialog/SystemDialog mnt/bin/SystemDialog cp ../Applications/ChanViewer/ChanViewer mnt/bin/ChanViewer cp ../Applications/Calculator/Calculator mnt/bin/Calculator cp ../Applications/SoundPlayer/SoundPlayer mnt/bin/SoundPlayer +cp ../Applications/DisplayProperties/DisplayProperties mnt/bin/DisplayProperties cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld cp ../Demos/HelloWorld2/HelloWorld2 mnt/bin/HelloWorld2 cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index e87cd3db11..4553530947 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -42,6 +42,7 @@ build_targets="$build_targets ../Libraries/LibVT" build_targets="$build_targets ../Applications/About" build_targets="$build_targets ../Applications/Calculator" build_targets="$build_targets ../Applications/ChanViewer" +build_targets="$build_targets ../Applications/DisplayProperties" build_targets="$build_targets ../Applications/Downloader" build_targets="$build_targets ../Applications/FileManager" build_targets="$build_targets ../Applications/FontEditor" diff --git a/Libraries/LibGUI/GTabWidget.cpp b/Libraries/LibGUI/GTabWidget.cpp index d0663c5b7e..180ddb5138 100644 --- a/Libraries/LibGUI/GTabWidget.cpp +++ b/Libraries/LibGUI/GTabWidget.cpp @@ -1,7 +1,7 @@ +#include #include #include #include -#include GTabWidget::GTabWidget(GWidget* parent) : GWidget(parent) diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index 4d5e7574db..fcc4c66c29 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -109,6 +109,7 @@ struct WSAPI_ServerMessage { DidSetWindowBackingStore, DidSetWallpaper, DidGetWallpaper, + DidSetResolution, DidSetWindowHasAlphaChannel, ScreenRectChanged, @@ -224,6 +225,7 @@ struct WSAPI_ClientMessage { Greeting, SetWallpaper, GetWallpaper, + SetResolution, SetWindowOverrideCursor, WM_SetActiveWindow, WM_SetWindowMinimized, @@ -260,6 +262,9 @@ struct WSAPI_ClientMessage { bool minimized; WSAPI_Point position; } wm; + struct { + WSAPI_Size resolution; + } wm_conf; struct { int menubar_id; int menu_id; diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index c71215473a..b2105ec930 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -289,6 +289,9 @@ bool WSClientConnection::handle_message(const WSAPI_ClientMessage& message, cons case WSAPI_ClientMessage::Type::GetWallpaper: CEventLoop::current().post_event(*this, make(client_id())); break; + case WSAPI_ClientMessage::Type::SetResolution: + CEventLoop::current().post_event(*this, make(client_id(), message.wm_conf.resolution.width, message.wm_conf.resolution.height)); + break; case WSAPI_ClientMessage::Type::SetWindowOverrideCursor: CEventLoop::current().post_event(*this, make(client_id(), message.window_id, (WSStandardCursor)message.cursor.cursor)); break; @@ -557,6 +560,15 @@ void WSClientConnection::handle_request(const WSAPIGetWallpaperRequest&) post_message(response); } +void WSClientConnection::handle_request(const WSAPISetResolutionRequest& request) +{ + WSWindowManager::the().set_resolution(request.resolution().width(), request.resolution().height()); + WSAPI_ServerMessage response; + response.type = WSAPI_ServerMessage::Type::DidSetResolution; + response.value = true; + post_message(response); +} + void WSClientConnection::handle_request(const WSAPISetWindowTitleRequest& request) { int window_id = request.window_id(); @@ -984,6 +996,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request) return handle_request(static_cast(request)); case WSEvent::APIGetWallpaperRequest: return handle_request(static_cast(request)); + case WSEvent::APISetResolutionRequest: + return handle_request(static_cast(request)); case WSEvent::APISetWindowOverrideCursorRequest: return handle_request(static_cast(request)); case WSEvent::WMAPISetActiveWindowRequest: diff --git a/Servers/WindowServer/WSClientConnection.h b/Servers/WindowServer/WSClientConnection.h index 16770464f7..bc2e12b22e 100644 --- a/Servers/WindowServer/WSClientConnection.h +++ b/Servers/WindowServer/WSClientConnection.h @@ -73,6 +73,7 @@ private: void handle_request(const WSAPISetWindowOpacityRequest&); void handle_request(const WSAPISetWallpaperRequest&); void handle_request(const WSAPIGetWallpaperRequest&); + void handle_request(const WSAPISetResolutionRequest&); void handle_request(const WSAPISetWindowOverrideCursorRequest&); void handle_request(const WSWMAPISetActiveWindowRequest&); void handle_request(const WSWMAPISetWindowMinimizedRequest&); diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 23096361d6..a9e7548f0c 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -300,6 +300,8 @@ void WSCompositor::set_resolution(int desired_width, int desired_height) return; m_wallpaper_path = {}; m_wallpaper = nullptr; + // Make sure it's impossible to set an invalid resolution + ASSERT(desired_width >= 640 && desired_height >= 480); WSScreen::the().set_resolution(desired_width, desired_height); init_bitmaps(); compose(); diff --git a/Servers/WindowServer/WSEvent.h b/Servers/WindowServer/WSEvent.h index b96c78beaa..4391d3f364 100644 --- a/Servers/WindowServer/WSEvent.h +++ b/Servers/WindowServer/WSEvent.h @@ -7,6 +7,7 @@ #include #include #include +#include #include class WSEvent : public CEvent { @@ -60,6 +61,7 @@ public: APIGetClipboardContentsRequest, APISetWallpaperRequest, APIGetWallpaperRequest, + APISetResolutionRequest, APISetWindowOverrideCursorRequest, APISetWindowHasAlphaChannelRequest, APIMoveWindowToFrontRequest, @@ -441,6 +443,20 @@ public: } }; +class WSAPISetResolutionRequest final : public WSAPIClientRequest { +public: + explicit WSAPISetResolutionRequest(int client_id, int width, int height) + : WSAPIClientRequest(WSEvent::APISetResolutionRequest, client_id), + m_resolution(width, height) + { + } + + Size resolution() const { return m_resolution; } + +private: + Size m_resolution; +}; + class WSAPISetWindowTitleRequest final : public WSAPIClientRequest { public: explicit WSAPISetWindowTitleRequest(int client_id, int window_id, const String& title)