예제 #1
0
파일: keyboard.c 프로젝트: hsoft/wlc
static bool
update_keys(struct chck_iter_pool *keys, uint32_t key, enum wl_keyboard_key_state state)
{
   assert(keys);

   uint32_t *k;
   chck_iter_pool_for_each(keys, k) {
      if (*k != key)
         continue;

      if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
         return false;

      wlc_dlog(WLC_DBG_KEYBOARD, "remove key: %u", *k);
      chck_iter_pool_remove(keys, --_I);
   }

   if (state == WL_KEYBOARD_KEY_STATE_PRESSED && !chck_iter_pool_push_back(keys, &key))
      return false;

   if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
      wlc_dlog(WLC_DBG_KEYBOARD, "add key: %u", key);

   return true;
}
예제 #2
0
파일: view.c 프로젝트: Hummer12007/wlc
bool
wlc_view_request_geometry(struct wlc_view *view, const struct wlc_geometry *r)
{
   assert(view && r);
   wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") requested geometry %ux%u+%d,%d", convert_to_wlc_handle(view), r->size.w, r->size.h, r->origin.x, r->origin.y);

   if (view->state.created && wlc_interface()->view.request.geometry) {
      WLC_INTERFACE_EMIT(view.request.geometry, convert_to_wlc_handle(view), r);
   } else {
      memcpy(&view->pending.geometry, r, sizeof(view->pending.geometry));
   }

   configure_view(view, view->pending.edges, &view->pending.geometry);
   wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") applied geometry %ux%u+%d,%d", convert_to_wlc_handle(view), view->pending.geometry.size.w, view->pending.geometry.size.h, view->pending.geometry.origin.x, view->pending.geometry.origin.y);
   return wlc_geometry_equals(r, &view->pending.geometry);
}
예제 #3
0
파일: gles2.c 프로젝트: boogerlad/wlc
static bool
surface_attach(struct ctx *context, struct wlc_context *bound, struct wlc_surface *surface, struct wlc_buffer *buffer)
{
   assert(context && bound && surface);

   struct wl_resource *wl_buffer;
   if (!buffer || !(wl_buffer = convert_to_wl_resource(buffer, "buffer"))) {
      surface_destroy(context, bound, surface);
      return true;
   }

   EGLint format;
   bool attached = false;

   struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(wl_buffer);
   if (shm_buffer) {
      attached = shm_attach(surface, buffer, shm_buffer);
   } else if (wlc_context_query_buffer(bound, (void*)wl_buffer, EGL_TEXTURE_FORMAT, &format)) {
      attached = egl_attach(context, bound, surface, buffer, format);
   } else {
      /* unknown buffer */
      wlc_log(WLC_LOG_WARN, "Unknown buffer");
   }

   if (attached)
      wlc_dlog(WLC_DBG_RENDER, "-> Attached surface (%" PRIuWLC ") with buffer of size (%ux%u)", convert_to_wlc_resource(surface), buffer->size.w, buffer->size.h);

   return attached;
}
예제 #4
0
파일: gles2.c 프로젝트: boogerlad/wlc
static void
surface_destroy(struct ctx *context, struct wlc_context *bound, struct wlc_surface *surface)
{
   (void)context;
   assert(context && bound && surface);
   surface_flush_textures(surface);
   surface_flush_images(bound, surface);
   wlc_dlog(WLC_DBG_RENDER, "-> Destroyed surface");
}
예제 #5
0
파일: xwm.c 프로젝트: Hummer12007/wlc
static void
set_geometry(xcb_window_t window, const struct wlc_geometry *g)
{
   assert(g);
   const uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
   const uint32_t values[] = { g->origin.x, g->origin.y, g->size.w, g->size.h };
   wlc_dlog(WLC_DBG_XWM, "-> Configure x11 window (%u) %ux%u+%d,%d", window, g->size.w, g->size.h, g->origin.x, g->origin.y);
   XCB_CALL(xcb_configure_window_checked(x11.connection, window, mask, (uint32_t*)&values));
   xcb_flush(x11.connection);
}
예제 #6
0
파일: xwm.c 프로젝트: Hummer12007/wlc
static bool
add_window(struct wlc_xwm *xwm, xcb_window_t window, bool override_redirect)
{
   assert(xwm);
   struct wlc_x11_window win = {0};
   win.id = window;
   win.override_redirect = override_redirect;
   const bool ret = chck_hash_table_set(&xwm->unpaired, window, &win);
   wlc_dlog(WLC_DBG_XWM, "-> Unpaired collisions (%u)", chck_hash_table_collisions(&xwm->unpaired));
   return ret;
}
예제 #7
0
파일: view.c 프로젝트: scarabeusiv/wlc
void
wlc_view_ack_surface_attach(struct wlc_view *view, struct wlc_surface *surface)
{
   assert(view && surface);

   if (view->x11.id) {
      surface->pending.opaque.extents = (pixman_box32_t){ 0, 0, surface->size.w, surface->size.h };
      view->surface_pending.visible = (struct wlc_geometry){ wlc_origin_zero, surface->size };
   }

   const bool resizing = (view->pending.state & WLC_BIT_RESIZING || view->commit.state & WLC_BIT_RESIZING);
   if (!resizing && !wlc_geometry_equals(&view->surface_pending.visible, &view->surface_commit.visible)) {
      struct wlc_geometry g = (struct wlc_geometry){ view->pending.geometry.origin, view->surface_pending.visible.size };
      wlc_view_request_geometry(view, &g);
   }

   view->surface_commit = view->surface_pending;
   wlc_dlog(WLC_DBG_COMMIT, "=> surface view %" PRIuWLC, convert_to_wlc_handle(view));
}

static bool
should_be_transformed_by_parent(struct wlc_view *view)
{
   return !(view->type & WLC_BIT_OVERRIDE_REDIRECT) && !(view->type & WLC_BIT_UNMANAGED);
}

void
wlc_view_get_bounds(struct wlc_view *view, struct wlc_geometry *out_bounds, struct wlc_geometry *out_visible)
{
   assert(view && out_bounds && out_bounds != out_visible);
   memcpy(out_bounds, &view->commit.geometry, sizeof(struct wlc_geometry));

   struct wlc_surface *surface;
   if (!(surface = convert_from_wlc_resource(view->surface, "surface")))
      return;

   if (should_be_transformed_by_parent(view)) {
      for (struct wlc_view *parent = convert_from_wlc_handle(view->parent, "view"); parent; parent = convert_from_wlc_handle(parent->parent, "view")) {
         out_bounds->origin.x += parent->commit.geometry.origin.x;
         out_bounds->origin.y += parent->commit.geometry.origin.y;
      }
   }

   if (view->xdg_surface && view->surface_commit.visible.size.w > 0 && view->surface_commit.visible.size.h > 0) {
      // xdg-surface client that draws drop shadows or other stuff.
      out_bounds->origin.x -= view->surface_commit.visible.origin.x;
      out_bounds->origin.y -= view->surface_commit.visible.origin.y;
      out_bounds->size.w += surface->size.w - view->surface_commit.visible.size.w;
      out_bounds->size.h += surface->size.h - view->surface_commit.visible.size.h;
   }

   // Make sure bounds is never 0x0 w/h
   wlc_size_max(&out_bounds->size, &(struct wlc_size){ 1, 1 }, &out_bounds->size);
예제 #8
0
파일: view.c 프로젝트: Hummer12007/wlc
bool
wlc_view_request_state(struct wlc_view *view, enum wlc_view_state_bit state, bool toggle)
{
   if (!view || !view->state.created)
      return false;

   if (!!(view->pending.state & state) == toggle) {
      // refresh geometry
      if (state == WLC_BIT_FULLSCREEN || state == WLC_BIT_MAXIMIZED)
         configure_view(view, view->pending.edges, &view->pending.geometry);
      return true;
   }

   wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") requested state %d", convert_to_wlc_handle(view), state);

   if (wlc_interface()->view.request.state) {
      WLC_INTERFACE_EMIT(view.request.state, convert_to_wlc_handle(view), state, toggle);
   } else {
      wlc_view_set_state_ptr(view, state, toggle);
   }

   wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") applied states %d", convert_to_wlc_handle(view), view->pending.state);
   return (!!(view->pending.state & state) == toggle);
}
예제 #9
0
파일: shell-surface.c 프로젝트: Cloudef/wlc
static void
wl_cb_shell_surface_resize(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, uint32_t edges)
{
   (void)client, (void)resource, (void)serial;

   struct wlc_seat *seat;
   if (!(seat = wl_resource_get_user_data(seat_resource)))
      return;

   if (!seat->pointer.focused.view)
      return;

   wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") requested resize", seat->pointer.focused.view);
   const struct wlc_point o = { seat->pointer.pos.x, seat->pointer.pos.y };
   WLC_INTERFACE_EMIT(view.request.resize, seat->pointer.focused.view, edges, &o);
}
예제 #10
0
파일: view.c 프로젝트: Hummer12007/wlc
void
wlc_view_set_surface(struct wlc_view *view, struct wlc_surface *surface)
{
   if (!view || view->surface == convert_to_wlc_resource(surface))
      return;

   wlc_handle old = view->surface;
   view->surface = convert_to_wlc_resource(surface);
   wlc_surface_attach_to_view(convert_from_wlc_resource(old, "surface"), NULL);
   wlc_surface_attach_to_view(surface, view);

   if (surface && surface->commit.attached) {
      wlc_view_map(view);
   } else {
      wlc_view_unmap(view);
   }

   wlc_dlog(WLC_DBG_RENDER, "-> Linked surface (%" PRIuWLC ") to view (%" PRIuWLC ")", convert_to_wlc_resource(surface), convert_to_wlc_handle(view));
}
예제 #11
0
파일: keyboard.c 프로젝트: hsoft/wlc
static void
send_release_for_keys(struct chck_iter_pool *resources, struct chck_iter_pool *keys)
{
   assert(keys);

   wlc_dlog(WLC_DBG_KEYBOARD, "release keys");

   uint32_t *k;
   uint32_t time = wlc_get_time(NULL);
   chck_iter_pool_for_each(keys, k) {
      wlc_resource *r;
      chck_iter_pool_for_each(resources, r) {
         struct wl_resource *wr;
         if (!(wr = wl_resource_from_wlc_resource(*r, "keyboard")))
            continue;

         uint32_t serial = wl_display_next_serial(wlc_display());
         wl_keyboard_send_key(wr, serial, time, *k, WL_KEYBOARD_KEY_STATE_RELEASED);
      }
   }
예제 #12
0
파일: xwm.c 프로젝트: Hummer12007/wlc
static void
read_properties(struct wlc_xwm *xwm, struct wlc_x11_window *win, const xcb_atom_t *props, size_t nmemb)
{
   assert(win);

   struct wlc_view *view;
   if (!(view = view_for_window(win)))
      return;

   xcb_get_property_cookie_t *cookies;
   if (!(cookies = chck_calloc_of(nmemb, sizeof(xcb_get_property_cookie_t))))
      return;

   for (uint32_t i = 0; i < nmemb; ++i)
      cookies[i] = xcb_get_property(x11.connection, 0, win->id, props[i], XCB_ATOM_ANY, 0, 2048);

   for (uint32_t i = 0; i < nmemb; ++i) {
      xcb_get_property_reply_t *reply;
      if (!(reply = xcb_get_property_reply(x11.connection, cookies[i], NULL)))
         continue;

      if (reply->type == XCB_ATOM_STRING || reply->type == x11.atoms[UTF8_STRING]) {
         // Class && Name
         // STRING == latin1, but we naively just read it as is. For full support we should convert to utf8.
         if (props[i] == XCB_ATOM_WM_CLASS) {
            wlc_view_set_class_ptr(view, xcb_get_property_value(reply), xcb_get_property_value_length(reply));
            wlc_dlog(WLC_DBG_XWM, "WM_CLASS: %s", view->data._class.data);
         } else if (props[i] == XCB_ATOM_WM_NAME || props[i] == x11.atoms[NET_WM_NAME]) {
            if (reply->type != XCB_ATOM_STRING  || !win->has_utf8_title) {
               wlc_view_set_title_ptr(view, xcb_get_property_value(reply), xcb_get_property_value_length(reply));
               win->has_utf8_title = true;
            }
            wlc_dlog(WLC_DBG_XWM, "(%d) %s %s %s", win->has_utf8_title, (reply->type == XCB_ATOM_STRING ? "STRING" : "UTF8_STRING"), (props[i] == XCB_ATOM_WM_NAME ? "WM_NAME" : "NET_WM_NAME"), view->data.title.data);
         }
      } else if (props[i] == XCB_ATOM_WM_TRANSIENT_FOR && reply->type == XCB_ATOM_WINDOW) {
         // Transient
         xcb_window_t *xid = xcb_get_property_value(reply);
         set_parent(xwm, win, *xid);
         wlc_dlog(WLC_DBG_XWM, "WM_TRANSIENT_FOR: %u", *xid);
      } else if (props[i] == x11.atoms[NET_WM_PID] && reply->type == XCB_ATOM_CARDINAL) {
         // PID
         wlc_dlog(WLC_DBG_XWM, "NET_WM_PID");
      } else if (props[i] == x11.atoms[NET_WM_WINDOW_TYPE] && reply->type == XCB_ATOM_ATOM) {
         // Window type
         view->type &= ~WLC_BIT_UNMANAGED | ~WLC_BIT_SPLASH | ~WLC_BIT_MODAL;
         xcb_atom_t *atoms = xcb_get_property_value(reply);
         for (uint32_t i = 0; i < reply->value_len; ++i) {
            if (atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_TOOLTIP] ||
                  atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_UTILITY] ||
                  atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_DND] ||
                  atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_DROPDOWN_MENU] ||
                  atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_POPUP_MENU] ||
                  atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_COMBO]) {
               wlc_view_set_type_ptr(view, WLC_BIT_UNMANAGED, true);
            }
            if (atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_DIALOG])
               wlc_view_set_type_ptr(view, WLC_BIT_MODAL, true);
            if (atoms[i] == x11.atoms[NET_WM_WINDOW_TYPE_SPLASH])
               wlc_view_set_type_ptr(view, WLC_BIT_SPLASH, true);
         }
         wlc_dlog(WLC_DBG_XWM, "NET_WM_WINDOW_TYPE: %u", view->type);
      } else if (props[i] == x11.atoms[WM_PROTOCOLS]) {
         xcb_atom_t *atoms = xcb_get_property_value(reply);
         for (uint32_t i = 0; i < reply->value_len; ++i) {
            if (atoms[i] == x11.atoms[WM_DELETE_WINDOW])
               win->has_delete_window = true;
         }
         wlc_dlog(WLC_DBG_XWM, "WM_PROTOCOLS: %u", view->type);
      } else if (props[i] == x11.atoms[WM_NORMAL_HINTS]) {
         wlc_dlog(WLC_DBG_XWM, "WM_NORMAL_HINTS");
      } else if (props[i] == x11.atoms[NET_WM_STATE]) {
         handle_state(win, xcb_get_property_value(reply), reply->value_len, NET_WM_STATE_ADD);
         wlc_dlog(WLC_DBG_XWM, "NET_WM_STATE");
      } else if (props[i] == x11.atoms[MOTIF_WM_HINTS]) {
         // Motif hints
         wlc_dlog(WLC_DBG_XWM, "MOTIF_WM_HINTS");
      }

      free(reply);
   }

   free(cookies);
}
예제 #13
0
파일: view.c 프로젝트: snells/wlc
void
wlc_view_commit_state(struct wlc_view *view, struct wlc_view_state *pending, struct wlc_view_state *out)
{
   struct wlc_surface *surface;
   if (!(surface = convert_from_wlc_resource(view->surface, "surface")))
      return;

   // FIXME: handle ping
#if 0
      struct wl_resource *r;
      if (view->shell_surface && (r = wl_resource_from_wlc_resource(view->shell_surface, "shell-surface")))
         wl_shell_surface_send_ping(r, wl_display_next_serial(wlc_display()));

      wlc_dlog(WLC_DBG_COMMIT, "=> ping view %zu", convert_to_wlc_handle(view));
      return;
#endif

   if (!view->state.created) {
      // Initial size of the view
      view->pending.geometry.size = surface->size;
      view->state.created = true;

      if (WLC_INTERFACE_EMIT_EXCEPT(view.created, false, convert_to_wlc_handle(view))) {
         wlc_view_close_ptr(view);
         return;
      }
   }

   if (!memcmp(pending, out, sizeof(struct wlc_view_state)))
      return;

   if (pending->state != out->state) {
      const struct {
         uint32_t bit;
         uint32_t state;
      } map[] = {
         { WLC_BIT_MAXIMIZED, XDG_SURFACE_STATE_MAXIMIZED },
         { WLC_BIT_FULLSCREEN, XDG_SURFACE_STATE_FULLSCREEN },
         { WLC_BIT_RESIZING, XDG_SURFACE_STATE_RESIZING },
         { WLC_BIT_ACTIVATED, XDG_SURFACE_STATE_ACTIVATED },
         { 0, 0 },
      };

      chck_iter_pool_flush(&view->wl_state);

      for (uint32_t i = 0; map[i].state != 0; ++i) {
         if (pending->state & map[i].bit)
            chck_iter_pool_push_back(&view->wl_state, &map[i].state);
      }
   }

   const bool size_changed = (!wlc_size_equals(&pending->geometry.size, &out->geometry.size) || !wlc_size_equals(&pending->geometry.size, &surface->size));
   wlc_dlog(WLC_DBG_COMMIT, "=> pending commit %zu (%d) pending: %ux%u commited: %ux%u surface: %ux%u", convert_to_wlc_handle(view), size_changed, pending->geometry.size.w, pending->geometry.size.h, out->geometry.size.w, out->geometry.size.h, surface->size.w, surface->size.h);

   if (pending->state != out->state || size_changed) {
      struct wl_resource *r;
      if (view->xdg_surface && (r = wl_resource_from_wlc_resource(view->xdg_surface, "xdg-surface"))) {
         const uint32_t serial = wl_display_next_serial(wlc_display());
         struct wl_array states = { .size = view->wl_state.items.used, .alloc = view->wl_state.items.allocated, .data = view->wl_state.items.buffer };
         xdg_surface_send_configure(r, pending->geometry.size.w, pending->geometry.size.h, &states, serial);
      } else if (view->shell_surface && (r = wl_resource_from_wlc_resource(view->shell_surface, "shell-surface"))) {
         wl_shell_surface_send_configure(r, pending->edges, pending->geometry.size.w, pending->geometry.size.h);
      }
   }

   if (view->x11.id) {
      if (!wlc_origin_equals(&pending->geometry.origin, &out->geometry.origin))
         wlc_x11_window_position(&view->x11, pending->geometry.origin.x, pending->geometry.origin.y);

      if (size_changed)
         wlc_x11_window_resize(&view->x11, pending->geometry.size.w, pending->geometry.size.h);
   }

   memcpy(out, pending, sizeof(struct wlc_view_state));
   wlc_dlog(WLC_DBG_COMMIT, "=> commit %zu", convert_to_wlc_handle(view));
}
예제 #14
0
파일: view.c 프로젝트: scarabeusiv/wlc
void
wlc_view_commit_state(struct wlc_view *view, struct wlc_view_state *pending, struct wlc_view_state *out)
{
   assert(view && pending && out);

   struct wlc_surface *surface;
   if (!(surface = convert_from_wlc_resource(view->surface, "surface")))
      return;

   // FIXME: handle ping
#if 0
      struct wl_resource *r;
      if (view->shell_surface && (r = wl_resource_from_wlc_resource(view->shell_surface, "shell-surface")))
         wl_shell_surface_send_ping(r, wl_display_next_serial(wlc_display()));

      wlc_dlog(WLC_DBG_COMMIT, "=> ping view %" PRIuWLC, convert_to_wlc_handle(view));
      return;
#endif

   if (!view->state.created) {
      // Initial size of the view
      view->pending.geometry.size = surface->size;
      view->state.created = true;

      if (WLC_INTERFACE_EMIT_EXCEPT(view.created, false, convert_to_wlc_handle(view))) {
         wlc_view_close_ptr(view);
         return;
      }
   }

   if (!memcmp(pending, out, sizeof(struct wlc_view_state)))
      return;

   if (pending->state != out->state) {
      const struct {
         enum wlc_view_state_bit bit;
         uint32_t state;
      } map[] = {
         { WLC_BIT_MAXIMIZED, XDG_SURFACE_STATE_MAXIMIZED },
         { WLC_BIT_FULLSCREEN, XDG_SURFACE_STATE_FULLSCREEN },
         { WLC_BIT_RESIZING, XDG_SURFACE_STATE_RESIZING },
         { WLC_BIT_ACTIVATED, XDG_SURFACE_STATE_ACTIVATED },
      };

      chck_iter_pool_flush(&view->wl_state);

      for (uint32_t i = 0; i < LENGTH(map); ++i) {
         if (pending->state & map[i].bit)
            chck_iter_pool_push_back(&view->wl_state, &map[i].state);
      }
   }

   const bool size_changed = (!wlc_size_equals(&pending->geometry.size, &out->geometry.size) || !wlc_size_equals(&pending->geometry.size, &surface->size));
   wlc_dlog(WLC_DBG_COMMIT, "=> pending view commit %" PRIuWLC " (%d) pending: %ux%u commited: %ux%u surface: %ux%u", convert_to_wlc_handle(view), size_changed, pending->geometry.size.w, pending->geometry.size.h, out->geometry.size.w, out->geometry.size.h, surface->size.w, surface->size.h);

   if (pending->state != out->state || size_changed)
      configure_view(view, pending->edges, &pending->geometry);

   *out = *pending;
   wlc_dlog(WLC_DBG_COMMIT, "=> commit view %" PRIuWLC, convert_to_wlc_handle(view));
}