xref: /aosp_15_r20/external/skia/tools/sk_app/unix/main_unix.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 
3 * Copyright 2016 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 
9 #include "include/core/SkTypes.h"
10 #include "src/core/SkTHash.h"
11 #include "tools/sk_app/Application.h"
12 #include "tools/sk_app/unix/Window_unix.h"
13 #include "tools/timer/Timer.h"
14 
15 using namespace skia_private;
16 
main(int argc,char ** argv)17 int main(int argc, char**argv) {
18     XInitThreads();
19     Display* display = XOpenDisplay(nullptr);
20 
21     sk_app::Application* app = sk_app::Application::Create(argc, argv, (void*)display);
22 
23     // Get the file descriptor for the X display
24     const int x11_fd = ConnectionNumber(display);
25 
26     bool done = false;
27     while (!done) {
28         if (0 == XPending(display)) {
29             // Only call select() when we have no events.
30 
31             // Create a file description set containing x11_fd
32             fd_set in_fds;
33             FD_ZERO(&in_fds);
34             FD_SET(x11_fd, &in_fds);
35 
36             // Set a sleep timer
37             struct timeval tv;
38             tv.tv_usec = 10;
39             tv.tv_sec = 0;
40 
41             // Wait for an event on the file descriptor or for timer expiration
42             (void)select(1, &in_fds, nullptr, nullptr, &tv);
43         }
44 
45         // Handle all pending XEvents (if any) and flush the input
46         // Only handle a finite number of events before finishing resize and paint..
47         if (int count = XPending(display)) {
48             // collapse any Expose and Resize events.
49             THashSet<sk_app::Window_unix*> pendingWindows;
50             while (count-- && !done) {
51                 XEvent event;
52                 XNextEvent(display, &event);
53 
54                 sk_app::Window_unix* win = sk_app::Window_unix::gWindowMap.find(event.xany.window);
55                 if (!win) {
56                     continue;
57                 }
58 
59                 // paint and resize events get collapsed
60                 switch (event.type) {
61                 case Expose:
62                     win->markPendingPaint();
63                     pendingWindows.add(win);
64                     break;
65                 case ConfigureNotify:
66                     win->markPendingResize(event.xconfigurerequest.width,
67                                            event.xconfigurerequest.height);
68                     pendingWindows.add(win);
69                     break;
70                 default:
71                     if (win->handleEvent(event)) {
72                         done = true;
73                     }
74                     break;
75                 }
76             }
77             pendingWindows.foreach([](sk_app::Window_unix* win) {
78                 win->finishResize();
79                 win->finishPaint();
80             });
81         } else {
82             // We are only really "idle" when the timer went off with zero events.
83             app->onIdle();
84         }
85 
86         XFlush(display);
87     }
88 
89     delete app;
90 
91     XCloseDisplay(display);
92 
93     return 0;
94 }
95