mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:42:45 +00:00 
			
		
		
		
	 57ff293a51
			
		
	
	
		57ff293a51
		
	
	
	
	
		
			
			This patch adds a simple GMessageBox that can run in a nested event loop.
Here's how you use it:
    GMessageBox box("Message text here", "Message window title");
    int result = box.exec();
The next step is to make the WindowServer respect the modality flag of
these windows and prevent interaction with other windows in the same
process until the modal window has been closed.
		
	
			
		
			
				
	
	
		
			129 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| #include <errno.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <fcntl.h>
 | |
| #include <assert.h>
 | |
| #include <sys/ioctl.h>
 | |
| #include <sys/select.h>
 | |
| #include "Terminal.h"
 | |
| #include <Kernel/KeyCode.h>
 | |
| #include <LibGUI/GApplication.h>
 | |
| #include <LibGUI/GWidget.h>
 | |
| #include <LibGUI/GWindow.h>
 | |
| #include <LibGUI/GMenuBar.h>
 | |
| #include <LibGUI/GAction.h>
 | |
| #include <LibGUI/GFontDatabase.h>
 | |
| 
 | |
| static void make_shell(int ptm_fd)
 | |
| {
 | |
|     pid_t pid = fork();
 | |
|     if (pid == 0) {
 | |
|         const char* tty_name = ptsname(ptm_fd);
 | |
|         if (!tty_name) {
 | |
|             perror("ptsname");
 | |
|             exit(1);
 | |
|         }
 | |
|         close(ptm_fd);
 | |
|         int pts_fd = open(tty_name, O_RDWR);
 | |
|         if (pts_fd < 0) {
 | |
|             perror("open");
 | |
|             exit(1);
 | |
|         }
 | |
| 
 | |
|         // NOTE: It's okay if this fails.
 | |
|         (void) ioctl(0, TIOCNOTTY);
 | |
| 
 | |
|         close(0);
 | |
|         close(1);
 | |
|         close(2);
 | |
| 
 | |
|         int rc = dup2(pts_fd, 0);
 | |
|         if (rc < 0) {
 | |
|             perror("dup2");
 | |
|             exit(1);
 | |
|         }
 | |
|         rc = dup2(pts_fd, 1);
 | |
|         if (rc < 0) {
 | |
|             perror("dup2");
 | |
|             exit(1);
 | |
|         }
 | |
|         rc = dup2(pts_fd, 2);
 | |
|         if (rc < 0) {
 | |
|             perror("dup2");
 | |
|             exit(1);
 | |
|         }
 | |
|         rc = close(pts_fd);
 | |
|         if (rc < 0) {
 | |
|             perror("close");
 | |
|             exit(1);
 | |
|         }
 | |
|         rc = ioctl(0, TIOCSCTTY);
 | |
|         if (rc < 0) {
 | |
|             perror("ioctl(TIOCSCTTY)");
 | |
|             exit(1);
 | |
|         }
 | |
|         char* args[] = { "/bin/sh", nullptr };
 | |
|         char* envs[] = { "TERM=xterm", nullptr };
 | |
|         rc = execve("/bin/sh", args, envs);
 | |
|         if (rc < 0) {
 | |
|             perror("execve");
 | |
|             exit(1);
 | |
|         }
 | |
|         ASSERT_NOT_REACHED();
 | |
|     }
 | |
| }
 | |
| 
 | |
| int main(int argc, char** argv)
 | |
| {
 | |
|     GApplication app(argc, argv);
 | |
| 
 | |
|     int ptm_fd = open("/dev/ptmx", O_RDWR);
 | |
|     if (ptm_fd < 0) {
 | |
|         perror("open(ptmx)");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     make_shell(ptm_fd);
 | |
| 
 | |
|     auto* window = new GWindow;
 | |
|     window->set_double_buffering_enabled(false);
 | |
|     window->set_should_exit_event_loop_on_close(true);
 | |
| 
 | |
|     Terminal terminal(ptm_fd);
 | |
|     window->set_has_alpha_channel(true);
 | |
|     window->set_main_widget(&terminal);
 | |
|     window->move_to(300, 300);
 | |
|     terminal.apply_size_increments_to_window(*window);
 | |
|     window->show();
 | |
| 
 | |
|     auto menubar = make<GMenuBar>();
 | |
| 
 | |
|     auto app_menu = make<GMenu>("Terminal");
 | |
|     app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) {
 | |
|         dbgprintf("Terminal: Quit menu activated!\n");
 | |
|         GApplication::the().quit(0);
 | |
|         return;
 | |
|     }));
 | |
|     menubar->add_menu(move(app_menu));
 | |
| 
 | |
|     auto font_menu = make<GMenu>("Font");
 | |
|     GFontDatabase::the().for_each_fixed_width_font([&] (const String& font_name) {
 | |
|         font_menu->add_action(GAction::create(font_name, [&terminal] (const GAction& action) {
 | |
|             terminal.set_font(GFontDatabase::the().get_by_name(action.text()));
 | |
|             terminal.force_repaint();
 | |
|         }));
 | |
|     });
 | |
|     menubar->add_menu(move(font_menu));
 | |
| 
 | |
|     auto help_menu = make<GMenu>("Help");
 | |
|     help_menu->add_action(GAction::create("About", [] (const GAction&) {
 | |
|         dbgprintf("FIXME: Implement Help/About\n");
 | |
|     }));
 | |
|     menubar->add_menu(move(help_menu));
 | |
| 
 | |
|     app.set_menubar(move(menubar));
 | |
| 
 | |
|     return app.exec();
 | |
| }
 |