summaryrefslogtreecommitdiff
path: root/src/window.cc
blob: 8c79b13857b57c1c112ffba0c8e53fb234a0bcc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "window.h"

#include <cstring>

#include "events.h"
#include "utils.h"
#include "vec.h"
#include "wlstate.h"
#include "xdg-shell.h"

static void wayc_surface_configure(void* data, struct xdg_surface* xdg_surface,
                                   u32 serial) {
  struct window_s* window = (struct window_s*)data;
  wayc_notnull(window);

  xdg_surface_ack_configure(xdg_surface, serial);
  wl_surface_commit(window->surface);
}

static void wayc_toplevel_configure(void* data,
                                    struct xdg_toplevel* xdg_toplevel,
                                    i32 width, i32 height,
                                    struct wl_array* states) {
  (void)xdg_toplevel;
  (void)states;

  struct window_s* window = (struct window_s*)data;
  wayc_notnull(window);

  struct eventloop_s* loop = window->loop;
  wayc_notnull(loop);

  struct event_s event = WAYC_EVENT_RESIZE(window, width, height);
  wayc_vec_push(&loop->events, &event);
}

static void wayc_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel) {
  (void)xdg_toplevel;

  struct window_s* window = (struct window_s*)data;
  wayc_notnull(window);

  struct eventloop_s* loop = window->loop;
  wayc_notnull(loop);

  struct event_s event = WAYC_EVENT_CLOSE(window);
  wayc_vec_push(&loop->events, &event);
}

static struct xdg_surface_listener WAYC_SURFACE_LISTENER = {
    wayc_surface_configure,
};

static struct xdg_toplevel_listener WAYC_TOPLEVEL_LISTENER = {
    wayc_toplevel_configure, wayc_toplevel_close, nullptr, nullptr};

enum window_error_e wayc_window_init(struct window_s* window, const char* name,
                                     struct eventloop_s* loop) {
  wayc_notnull(window);
  wayc_notnull(loop);
  memset(window, 0, sizeof(*window));

  struct wlstate_s* wlstate = &loop->state;

  wl_surface_t surface = wl_compositor_create_surface(wlstate->compositor);
  if (surface == nullptr) return WINDOW_ERROR_WL_SURFACE_CREATION;

  xdg_surface_t xdg_surface =
      xdg_wm_base_get_xdg_surface(wlstate->wm_base, surface);
  if (xdg_surface == nullptr) {
    wl_surface_destroy(surface);
    return WINDOW_ERROR_XDG_SURFACE_CREATION;
  }

  xdg_surface_add_listener(xdg_surface, &WAYC_SURFACE_LISTENER, window);

  xdg_toplevel_t xdg_toplevel = xdg_surface_get_toplevel(xdg_surface);
  if (xdg_toplevel == nullptr) {
    xdg_surface_destroy(xdg_surface);
    wl_surface_destroy(surface);
    return WINDOW_ERROR_XDG_TOPLEVEL_CREATION;
  }

  xdg_toplevel_add_listener(xdg_toplevel, &WAYC_TOPLEVEL_LISTENER, window);
  xdg_toplevel_set_title(xdg_toplevel, name);
  wl_surface_commit(surface);

  window->surface = surface;
  window->xdg_surface = xdg_surface;
  window->xdg_toplevel = xdg_toplevel;
  window->loop = loop;

  return WINDOW_ERROR_NONE;
}

void wayc_window_deinit(struct window_s* window) {
  wayc_notnull(window);

  if (window->surface == nullptr || window->xdg_surface == nullptr ||
      window->xdg_toplevel == nullptr)
    return;

  xdg_toplevel_destroy(window->xdg_toplevel);
  xdg_surface_destroy(window->xdg_surface);
  wl_surface_destroy(window->surface);

  window->xdg_toplevel = nullptr;
  window->xdg_surface = nullptr;
  window->surface = nullptr;
}

void wayc_window_redraw(struct window_s* window, struct eventloop_s* loop) {
  wayc_notnull(window);
  wayc_notnull(loop);

  struct event_s event = WAYC_EVENT_FRAME(window);
  wayc_vec_push(&loop->events, &event);
}