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 "include/private/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
15int main(int argc, char**argv) {
16    XInitThreads();
17    Display* display = XOpenDisplay(nullptr);
18
19    sk_app::Application* app = sk_app::Application::Create(argc, argv, (void*)display);
20
21    // Get the file descriptor for the X display
22    const int x11_fd = ConnectionNumber(display);
23
24    bool done = false;
25    while (!done) {
26        if (0 == XPending(display)) {
27            // Only call select() when we have no events.
28
29            // Create a file description set containing x11_fd
30            fd_set in_fds;
31            FD_ZERO(&in_fds);
32            FD_SET(x11_fd, &in_fds);
33
34            // Set a sleep timer
35            struct timeval tv;
36            tv.tv_usec = 10;
37            tv.tv_sec = 0;
38
39            // Wait for an event on the file descriptor or for timer expiration
40            (void)select(1, &in_fds, nullptr, nullptr, &tv);
41        }
42
43        // Handle all pending XEvents (if any) and flush the input
44        // Only handle a finite number of events before finishing resize and paint..
45        if (int count = XPending(display)) {
46            // collapse any Expose and Resize events.
47            SkTHashSet<sk_app::Window_unix*> pendingWindows;
48            while (count-- && !done) {
49                XEvent event;
50                XNextEvent(display, &event);
51
52                sk_app::Window_unix* win = sk_app::Window_unix::gWindowMap.find(event.xany.window);
53                if (!win) {
54                    continue;
55                }
56
57                // paint and resize events get collapsed
58                switch (event.type) {
59                case Expose:
60                    win->markPendingPaint();
61                    pendingWindows.add(win);
62                    break;
63                case ConfigureNotify:
64                    win->markPendingResize(event.xconfigurerequest.width,
65                                           event.xconfigurerequest.height);
66                    pendingWindows.add(win);
67                    break;
68                default:
69                    if (win->handleEvent(event)) {
70                        done = true;
71                    }
72                    break;
73                }
74            }
75            pendingWindows.foreach([](sk_app::Window_unix* win) {
76                win->finishResize();
77                win->finishPaint();
78            });
79        } else {
80            // We are only really "idle" when the timer went off with zero events.
81            app->onIdle();
82        }
83
84        XFlush(display);
85    }
86
87    delete app;
88
89    XCloseDisplay(display);
90
91    return 0;
92}
93