Hello community, here is the log from the commit of package wlc for openSUSE:Factory checked in at 2016-08-20 12:27:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/wlc (Old) and /work/SRC/openSUSE:Factory/.wlc.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "wlc" Changes: -------- --- /work/SRC/openSUSE:Factory/wlc/wlc.changes 2016-06-02 09:38:37.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.wlc.new/wlc.changes 2016-08-20 12:27:16.000000000 +0200 @@ -2 +2,22 @@ -Mon May 30 18:25:56 UTC 2016 - tc...@suse.com +Tue Aug 2 20:05:32 UTC 2016 - sleep_wal...@opensuse.org + +- bump to 0.0.5 + implement wlc_view_get_pid() + xwm: do not try to focus override_redirect windows + keyboard: Send focus out only on way<->x11 change + view: Return visible geo as input area for x views + +------------------------------------------------------------------- +Sun Jul 31 12:41:23 UTC 2016 - sleep_wal...@opensuse.org + +- bump to 0.0.4 + Bump version to 0.0.4 + HiDPI, surface and subsurface related features and fixes + s/wlc_resource/wlc_handle/ + Remove spammy debug log. + add WLC_DRAW_INPUT env var + xwm features + (for complete list of changes check git log) + +------------------------------------------------------------------- +Mon May 30 18:25:56 UTC 2016 - sleep_wal...@opensuse.org @@ -7 +28 @@ -Mon May 23 10:02:13 UTC 2016 - tc...@suse.com +Mon May 23 10:02:13 UTC 2016 - sleep_wal...@opensuse.org @@ -16 +37 @@ -Thu May 5 12:50:48 UTC 2016 - tc...@suse.com +Thu May 5 12:50:48 UTC 2016 - sleep_wal...@opensuse.org @@ -28 +49 @@ -Fri Apr 15 19:19:04 UTC 2016 - tc...@suse.com +Fri Apr 15 19:19:04 UTC 2016 - sleep_wal...@opensuse.org Old: ---- wlc-0.0.3.tar.bz2 wlc-0.0.3.tar.bz2.asc New: ---- wlc-0.0.5.tar.bz2 wlc-0.0.5.tar.bz2.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ wlc.spec ++++++ --- /var/tmp/diff_new_pack.pDWImx/_old 2016-08-20 12:27:17.000000000 +0200 +++ /var/tmp/diff_new_pack.pDWImx/_new 2016-08-20 12:27:17.000000000 +0200 @@ -19,7 +19,7 @@ %define wayland_minimal 1.7.0 Name: wlc -Version: 0.0.3 +Version: 0.0.5 Release: 0 Summary: A Wayland Compositor Library License: MIT ++++++ wlc-0.0.3.tar.bz2 -> wlc-0.0.5.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/CMakeLists.txt new/wlc-0.0.5/CMakeLists.txt --- old/wlc-0.0.3/CMakeLists.txt 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/CMakeLists.txt 2016-08-02 19:57:11.000000000 +0200 @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.1) -PROJECT(wlc VERSION 0.0.3 LANGUAGES C) +PROJECT(wlc VERSION 0.0.5 LANGUAGES C) set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/CMake") # Subprojects @@ -83,7 +83,7 @@ create_custom_linker_flags(Upstream ${ldflags}) create_custom_compiler_flags(Upstream -g -O2 ${cflags}) -add_compiler_warnings(-Wall -Wextra -Wno-variadic-macros -Wno-long-long -Wformat=2 -Winit-self -Wfloat-equal -Wcast-align -Wpointer-arith -Wmissing-prototypes) +add_compiler_warnings(-Wall -Wextra -Wno-variadic-macros -Wno-long-long -Wformat=2 -Winit-self -Wfloat-equal -Wcast-align -Wpointer-arith -Wmissing-prototypes -Wno-nonnull-compare) if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) add_compiler_warnings(-Wsuggest-attribute=pure -Wsuggest-attribute=const) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/example/example.c new/wlc-0.0.5/example/example.c --- old/wlc-0.0.3/example/example.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/example/example.c 2016-08-02 19:57:11.000000000 +0200 @@ -73,7 +73,7 @@ // you probably don't want to layout certain type of windows in wm const struct wlc_size *r; - if (!(r = wlc_output_get_resolution(output))) + if (!(r = wlc_output_get_virtual_resolution(output))) return; size_t memb; @@ -81,11 +81,22 @@ bool toggle = false; uint32_t y = 0; - uint32_t w = r->w / 2, h = r->h / chck_maxu32((1 + memb) / 2, 1); + const uint32_t n = chck_maxu32((1 + memb) / 2, 1); + const uint32_t w = r->w / 2, h = r->h / n; + const uint32_t ew = r->w - w * 2, eh = r->h - h * n; for (size_t i = 0; i < memb; ++i) { - struct wlc_geometry g = { { (toggle ? w : 0), y }, { (!toggle && i == memb - 1 ? r->w : w), h } }; + const struct wlc_geometry g = { + .origin = { + .x = (toggle ? w + ew : 0), + .y = y + }, + .size = { + .w = (!toggle && i == memb - 1 ? r->w : (toggle ? w : w + ew)), + .h = (i < 2 ? h + eh : h) + } + }; wlc_view_set_geometry(views[i], 0, &g); - y = y + (!(toggle = !toggle) ? h : 0); + y = y + (!(toggle = !toggle) ? g.size.h : 0); } } @@ -163,6 +174,16 @@ char *terminal = (getenv("TERMINAL") ? getenv("TERMINAL") : "weston-terminal"); wlc_exec(terminal, (char *const[]){ terminal, NULL }); return true; + } else if (modifiers->mods & WLC_BIT_MOD_CTRL && sym >= XKB_KEY_1 && sym <= XKB_KEY_9) { + size_t memb; + const wlc_handle *outputs = wlc_get_outputs(&memb); + const uint32_t scale = (sym - XKB_KEY_1) + 1; + + for (size_t i = 0; i < memb; ++i) + wlc_output_set_resolution(outputs[i], wlc_output_get_resolution(outputs[i]), scale); + + printf("scale: %u\n", scale); + return true; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/include/wlc/wlc.h new/wlc-0.0.5/include/wlc/wlc.h --- old/wlc-0.0.3/include/wlc/wlc.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/include/wlc/wlc.h 2016-08-02 19:57:11.000000000 +0200 @@ -8,6 +8,7 @@ #include <wlc/defines.h> #include <wlc/geometry.h> #include <xkbcommon/xkbcommon-keysyms.h> +#include <sys/types.h> struct wlc_event_source; @@ -61,6 +62,7 @@ WLC_BIT_PROPERTY_TITLE = 1<<0, WLC_BIT_PROPERTY_CLASS = 1<<1, WLC_BIT_PROPERTY_APP_ID = 1<<2, + WLC_BIT_PROPERTY_PID = 1<<3, }; /** wlc_view_set_geometry(); Edges in interface interface.view.request.resize function. */ @@ -278,11 +280,25 @@ /** Wake up / sleep. */ void wlc_output_set_sleep(wlc_handle output, bool sleep); -/** Get resolution. */ +/** + * Get real resolution. + * Resolution applied by either wlc_output_set_resolution call or initially. + * Do not use this for coordinate boundary. + */ const struct wlc_size* wlc_output_get_resolution(wlc_handle output); +/** + * Get virtual resolution. + * Resolution with transformations applied for proper rendering for example on high density displays. + * Use this to figure out coordinate boundary. + */ +const struct wlc_size* wlc_output_get_virtual_resolution(wlc_handle output); + /** Set resolution. */ -WLC_NONULL void wlc_output_set_resolution(wlc_handle output, const struct wlc_size *resolution); +WLC_NONULL void wlc_output_set_resolution(wlc_handle output, const struct wlc_size *resolution, uint32_t scale); + +/** Get scale factor. */ +uint32_t wlc_output_get_scale(wlc_handle output); /** Get current visibility bitmask. */ uint32_t wlc_output_get_mask(wlc_handle output); @@ -374,6 +390,9 @@ /** Get app id. (xdg-surface only) */ const char* wlc_view_get_app_id(wlc_handle view); +/** Get pid. */ +pid_t wlc_view_get_pid(wlc_handle view); + /** -- Input API * Very recent stuff, things may change. * XXX: This api is dumb and assumes there is only single xkb state and keymap. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/man/man3/wlc_view_get_pid.3 new/wlc-0.0.5/man/man3/wlc_view_get_pid.3 --- old/wlc-0.0.3/man/man3/wlc_view_get_pid.3 1970-01-01 01:00:00.000000000 +0100 +++ new/wlc-0.0.5/man/man3/wlc_view_get_pid.3 2016-08-02 19:57:11.000000000 +0200 @@ -0,0 +1,32 @@ +.TH WLC_VIEW_GET_PID 3 2016-07-29 WLC "WLC Core API Functions" + +.SH NAME +wlc_view_get_pid - get the process id for a given view + +.SH SYNOPSIS +.B #include <wlc/wlc.h> + +.BI "pid_t wlc_view_get_pid(wlc_handle "view ");" + +.SS Wayland protocol requirements: +.RS +.BR wlc_view_get_pid (): +xdg_shell +.RE + +.SH DESCRIPTION +.BR wlc_view_get_pid () +can be used to acquire the process id of a given +.I view. + +.SH RETURN VALUE +.BR wlc_view_get_pid () +returns the process id for +.I view +if it is available. Returns 0 (not a valid pid) if it is not. For X11 +views this requires the application set the __NET_WM_PID property. + +.SH ALSO SEE +The XDG Shell protocol extension +.UR http://cgit.freedesktop.org/wayland/weston/tree/protocol/xdg-shell.xml +.UE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/output.c new/wlc-0.0.5/src/compositor/output.c --- old/wlc-0.0.3/src/compositor/output.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/output.c 2016-08-02 19:57:11.000000000 +0200 @@ -87,9 +87,10 @@ (output->information.model.data ? output->information.model.data : "model"), output->information.transform); - assert(output->information.scale > 0); - if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) - wl_output_send_scale(resource, output->information.scale); + if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) { + assert(output->scale > 0); + wl_output_send_scale(resource, output->scale); + } struct wlc_output_mode *mode; chck_iter_pool_for_each(&output->information.modes, mode) { @@ -149,7 +150,7 @@ visible = true; if (!should_blit) - return true; + break; } if (should_blit) @@ -164,7 +165,7 @@ { assert(output && output->blit); - const size_t gsz = output->resolution.w * output->resolution.h; + const size_t gsz = output->virtual.w * output->virtual.h; memset(output->blit, false, gsz); wlc_handle *h; @@ -175,6 +176,7 @@ !(s = convert_from_wlc_resource(v->surface, "surface"))) continue; + wlc_view_commit_state(v, &v->pending, &v->commit); const bool vis = view_visible(v, s, output->active.mask); // This place sucks for this, but otherwise we would need API level interaction. @@ -196,16 +198,17 @@ struct wlc_geometry o; struct wlc_point a, b; const bool should_blit = wlc_view_get_opaque(v, &o); - a.x = chck_clamp32(o.origin.x, 0, output->resolution.w); - a.y = chck_clamp32(o.origin.y, 0, output->resolution.h); - b.x = chck_clamp32((o.origin.x + o.size.w), 1, output->resolution.w); - b.y = chck_clamp32((o.origin.y + o.size.h), 1, output->resolution.h); + a.x = chck_clamp32(o.origin.x, 0, output->virtual.w); + a.y = chck_clamp32(o.origin.y, 0, output->virtual.h); + b.x = chck_clamp32((o.origin.x + o.size.w), 1, output->virtual.w); + b.y = chck_clamp32((o.origin.y + o.size.h), 1, output->virtual.h); - if (!blit(output->blit, &output->resolution, &a, &b, should_blit)) { - wlc_dlog(WLC_DBG_RENDER_LOOP, "%" PRIuWLC " is not visible", *h); + if (!blit(output->blit, &output->virtual, &a, &b, should_blit)) { + wlc_dlog(WLC_DBG_RENDER_LOOP, "%" PRIuWLC " is not visible (%d,%d+%d,%d %d,%d+%ux%u)", *h, a.x, a.y, b.x, b.y, o.origin.x, o.origin.y, o.size.w, o.size.h); continue; } + wlc_dlog(WLC_DBG_RENDER_LOOP, "%" PRIuWLC " is visible (%d,%d+%d,%d %d,%d+%ux%u)", *h, a.x, a.y, b.x, b.y, o.origin.x, o.origin.y, o.size.w, o.size.h); chck_iter_pool_push_front(visible, &v); } @@ -236,10 +239,15 @@ static void render_subsurface(struct wlc_output *output, struct wlc_surface *surface, struct wlc_point offset, struct wlc_coordinate_scale parent_scale) { - const struct wlc_geometry g = (struct wlc_geometry) { - .origin = {offset.x + parent_scale.w * (surface->commit.subsurface_position.x + surface->commit.offset.x), - offset.y + parent_scale.h * (surface->commit.subsurface_position.y + surface->commit.offset.y)}, - .size = surface->size + const struct wlc_geometry g = { + .origin = { + .x = offset.x + parent_scale.w * (surface->commit.subsurface_position.x + surface->commit.offset.x), + .y = offset.y + parent_scale.h * (surface->commit.subsurface_position.y + surface->commit.offset.y) + }, + .size = { + .w = surface->size.w * parent_scale.w, + .h = surface->size.h * parent_scale.h + }, }; wlc_render_surface_paint(&output->render, &output->context, surface, &g); } @@ -247,9 +255,9 @@ static void subsurfaces_render(struct wlc_output *output, struct wlc_surface *surface, struct wlc_coordinate_scale parent_scale, struct chck_iter_pool *callbacks, struct wlc_point offset) { - if (!surface) return; + /* do not render view's main surface twice */ if (surface->parent) render_subsurface(output, surface, offset, parent_scale); @@ -259,8 +267,8 @@ subsurfaces_render(output, convert_from_wlc_resource(*sub, "surface"), surface->coordinate_transform, callbacks, (struct wlc_point) { - offset.x + (surface->parent ? 0 : surface->commit.subsurface_position.x / parent_scale.w), - offset.y + (surface->parent ? 0 : surface->commit.subsurface_position.y / parent_scale.h) + offset.x + (surface->parent ? 0 : surface->commit.subsurface_position.x / parent_scale.w), + offset.y + (surface->parent ? 0 : surface->commit.subsurface_position.y / parent_scale.h) }); } @@ -282,7 +290,6 @@ if (!(surface = convert_from_wlc_resource(view->surface, "surface"))) return; - wlc_view_commit_state(view, &view->pending, &view->commit); WLC_INTERFACE_EMIT(view.render.pre, convert_to_wlc_handle(view)); wlc_render_flush_fakefb(&output->render, &output->context); wlc_render_view_paint(&output->render, &output->context, view); @@ -315,7 +322,7 @@ return false; } - wlc_render_resolution(&output->render, &output->context, &output->mode, &output->resolution); + wlc_render_resolution(&output->render, &output->context, &output->mode, &output->virtual, output->scale); if (output->state.sleeping) { // fake sleep @@ -643,7 +650,7 @@ wlc_log(WLC_LOG_INFO, "%s Chose mode (%u) %dx%d", output->information.name.data, output->active.mode, mode->width, mode->height); output->mode = (struct wlc_size){ mode->width, mode->height }; mode->flags |= WL_OUTPUT_MODE_CURRENT; - set_resolution = wlc_output_set_resolution_ptr(output, &output->mode); + set_resolution = wlc_output_set_resolution_ptr(output, &output->mode, output->scale); } if (!set_resolution) @@ -741,24 +748,28 @@ } bool -wlc_output_set_resolution_ptr(struct wlc_output *output, const struct wlc_size *resolution) +wlc_output_set_resolution_ptr(struct wlc_output *output, const struct wlc_size *resolution, uint32_t scale) { if (!output) return false; - assert(resolution && resolution->w != 0 && resolution->h != 0); + assert(resolution && resolution->w != 0 && resolution->h != 0 && scale != 0); - if (resolution->w == 0 || resolution->h == 0) { - wlc_log(WLC_LOG_WARN, "Tried to set resolution of output %" PRIuWLC "to %ux%u", convert_to_wlc_handle(output), resolution->w, resolution->h); + if (resolution->w == 0 || resolution->h == 0 || scale == 0) { + wlc_log(WLC_LOG_WARN, "Tried to set resolution of output %" PRIuWLC "to %ux%u / %u", convert_to_wlc_handle(output), resolution->w, resolution->h, scale); return false; } - if (wlc_size_equals(resolution, &output->resolution)) + if (output->scale == scale && wlc_size_equals(resolution, &output->resolution)) return false; + struct wlc_size virtual = *resolution; + virtual.w /= scale; + virtual.h /= scale; + size_t gsz; - if (chck_mul_ofsz(resolution->w, resolution->h, &gsz)) { - wlc_log(WLC_LOG_WARN, "Requested resolution %ux%u overflows when multiplied, ignoring resolution", resolution->w, resolution->h); + if (chck_mul_ofsz(virtual.w, virtual.h, &gsz)) { + wlc_log(WLC_LOG_WARN, "Requested resolution %ux%u (%ux%u) overflows when multiplied, ignoring resolution", resolution->w, resolution->h, virtual.w, virtual.h); return false; } @@ -767,6 +778,8 @@ struct wlc_size old = output->resolution; output->resolution = *resolution; + output->virtual = virtual; + output->scale = scale; output_push_to_resources(output); WLC_INTERFACE_EMIT(output.resolution, convert_to_wlc_handle(output), &old, &output->resolution); @@ -868,10 +881,23 @@ return get(convert_from_wlc_handle(output, "output"), offsetof(struct wlc_output, resolution)); } +WLC_API const struct wlc_size* +wlc_output_get_virtual_resolution(wlc_handle output) +{ + return get(convert_from_wlc_handle(output, "output"), offsetof(struct wlc_output, virtual)); +} + WLC_API void -wlc_output_set_resolution(wlc_handle output, const struct wlc_size *resolution) +wlc_output_set_resolution(wlc_handle output, const struct wlc_size *resolution, uint32_t scale) +{ + wlc_output_set_resolution_ptr(convert_from_wlc_handle(output, "output"), resolution, scale); +} + +WLC_API uint32_t +wlc_output_get_scale(wlc_handle output) { - wlc_output_set_resolution_ptr(convert_from_wlc_handle(output, "output"), resolution); + void *ptr = get(convert_from_wlc_handle(output, "output"), offsetof(struct wlc_output, scale)); + return (ptr ? *(uint32_t*)ptr : 1); } WLC_API bool @@ -997,6 +1023,7 @@ output->active.mode = UINT_MAX; output->state.ims = 41; + output->scale = 1; wlc_output_set_sleep_ptr(output, false); wlc_output_set_mask_ptr(output, (1<<0)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/output.h new/wlc-0.0.5/src/compositor/output.h --- old/wlc-0.0.3/src/compositor/output.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/output.h 2016-08-02 19:57:11.000000000 +0200 @@ -33,7 +33,6 @@ int32_t x, y; int32_t physical_width, physical_height; int32_t subpixel; - int32_t scale; uint32_t connector_id; enum wl_output_transform transform; enum wlc_connector_type connector; @@ -41,7 +40,7 @@ struct wlc_output { struct wlc_source resources; - struct wlc_size mode, resolution; + struct wlc_size mode, resolution, virtual; struct wlc_output_information information; struct wlc_backend_surface bsurface; struct wlc_context context; @@ -55,6 +54,10 @@ // Used to do visibility checks bool *blit; + // Scale of the output + // Affects virtual resolution by dividing with the scale + uint32_t scale; + struct { struct wl_event_source *idle; } timer; @@ -102,7 +105,7 @@ void wlc_output_focus_ptr(struct wlc_output *output); void wlc_output_set_sleep_ptr(struct wlc_output *output, bool sleep); -WLC_NONULLV(2) bool wlc_output_set_resolution_ptr(struct wlc_output *output, const struct wlc_size *resolution); +WLC_NONULLV(2) bool wlc_output_set_resolution_ptr(struct wlc_output *output, const struct wlc_size *resolution, uint32_t scale); void wlc_output_set_mask_ptr(struct wlc_output *output, uint32_t mask); WLC_NONULLV(2) void wlc_output_get_pixels_ptr(struct wlc_output *output, bool (*pixels)(const struct wlc_size *size, uint8_t *rgba, void *arg), void *arg); bool wlc_output_set_views_ptr(struct wlc_output *output, const wlc_handle *views, size_t memb); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/seat/keyboard.c new/wlc-0.0.5/src/compositor/seat/keyboard.c --- old/wlc-0.0.3/src/compositor/seat/keyboard.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/seat/keyboard.c 2016-08-02 19:57:11.000000000 +0200 @@ -142,7 +142,7 @@ if (!(surface = wl_resource_from_wlc_resource(view->surface, "surface"))) goto out; - if (is_x11_view(view)) + if (is_x11_view(view) && (!new_focus || !is_x11_view(new_focus))) wlc_x11_window_set_active(&view->x11, false); wlc_resource *r; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/seat/pointer.c new/wlc-0.0.5/src/compositor/seat/pointer.c --- old/wlc-0.0.3/src/compositor/seat/pointer.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/seat/pointer.c 2016-08-02 19:57:11.000000000 +0200 @@ -63,8 +63,27 @@ return (view->mask & mask); } +static bool +is_inside_view_input_region(struct wlc_pointer *pointer, struct wlc_view *view) +{ + if (!view) + return false; + + // FIXME: We should handle subsurfaces as well... + + struct wlc_geometry b; + wlc_view_get_input(view, &b); + + const struct wlc_geometry point = { + .origin = { .x = pointer->pos.x, .y = pointer->pos.y }, + .size = { .w = 1, .h = 1 } + }; + + return wlc_geometry_contains(&b, &point); +} + static void -find_surface_at_position_recursive(struct wlc_pointer *pointer, struct wlc_surface *parent, struct wlc_focused_surface *out) +find_surface_at_position_recursive(const struct wlc_geometry *point, struct wlc_surface *parent, struct wlc_focused_surface *out) { wlc_resource *sub; chck_iter_pool_for_each(&parent->subsurface_list, sub) { @@ -77,14 +96,17 @@ out->offset.x += dx; out->offset.y += dy; - find_surface_at_position_recursive(pointer, subsurface, out); + find_surface_at_position_recursive(point, subsurface, out); + + const struct wlc_geometry b = { + .origin = out->offset, + .size = subsurface->size + }; if (out->id) return; - if (out->offset.x <= pointer->pos.x && out->offset.y <= pointer->pos.y && - subsurface->size.w + out->offset.x >= pointer->pos.x && - subsurface->size.h + out->offset.y >= pointer->pos.y) { + if (wlc_geometry_contains(&b, point)) { out->id = *sub; return; } @@ -104,25 +126,28 @@ out->id = 0; + const struct wlc_geometry point = { + .origin = { .x = pointer->pos.x, .y = pointer->pos.y }, + .size = { .w = 1, .h = 1 } + }; + wlc_handle *h; chck_iter_pool_for_each_reverse(&output->views, h) { struct wlc_view *view; if (!(view = convert_from_wlc_handle(*h, "view")) || !view_visible(view, output->active.mask)) continue; - struct wlc_geometry b; - wlc_view_get_bounds(view, &b, NULL); + struct wlc_geometry b, v; + wlc_view_get_bounds(view, &b, &v); struct wlc_surface *surface; if ((surface = convert_from_wlc_resource(view->surface, "surface"))) { out->offset = b.origin; - find_surface_at_position_recursive(pointer, surface, out); + find_surface_at_position_recursive(&point, surface, out); if (out->id) { return true; - } else if (b.origin.x <= pointer->pos.x && b.origin.y <= pointer->pos.y && - surface->size.w + b.origin.x >= pointer->pos.x && - surface->size.h + b.origin.y >= pointer->pos.y) { + } else if (wlc_geometry_contains(&v, &point)) { out->id = view->surface; return true; } @@ -289,6 +314,9 @@ } } + if (!is_inside_view_input_region(pointer, convert_from_wlc_handle(pointer->focused.view, "view"))) + return; + wlc_resource *r; chck_iter_pool_for_each(&pointer->focused.resources, r) { struct wl_resource *wr; @@ -305,6 +333,9 @@ { assert(pointer); + if (!is_inside_view_input_region(pointer, convert_from_wlc_handle(pointer->focused.view, "view"))) + return; + wlc_resource *r; chck_iter_pool_for_each(&pointer->focused.resources, r) { struct wl_resource *wr; @@ -338,6 +369,9 @@ if (!focused.id || !pass) return; + if (!is_inside_view_input_region(pointer, convert_from_wlc_handle(pointer->focused.view, "view"))) + return; + wlc_resource *r; chck_iter_pool_for_each(&pointer->focused.resources, r) { struct wl_resource *wr; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/seat/seat.c new/wlc-0.0.5/src/compositor/seat/seat.c --- old/wlc-0.0.3/src/compositor/seat/seat.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/seat/seat.c 2016-08-02 19:57:11.000000000 +0200 @@ -145,11 +145,12 @@ struct wlc_input_event *ev = data; struct wlc_output *output = convert_from_wlc_handle(compositor->active.output, "output"); + + const struct wlc_size resolution = (output ? output->virtual : wlc_size_zero); + switch (ev->type) { case WLC_INPUT_EVENT_MOTION: { - const struct wlc_size resolution = (output ? output->resolution : wlc_size_zero); - const struct wlc_pointer_origin pos = { chck_clamp(seat->pointer.pos.x + ev->motion.dx, 0, resolution.w), chck_clamp(seat->pointer.pos.y + ev->motion.dy, 0, resolution.h), @@ -162,8 +163,6 @@ case WLC_INPUT_EVENT_MOTION_ABSOLUTE: { - const struct wlc_size resolution = (output ? output->resolution : wlc_size_zero); - const struct wlc_pointer_origin pos = { ev->motion_abs.x(ev->motion_abs.internal, resolution.w), ev->motion_abs.y(ev->motion_abs.internal, resolution.h) @@ -183,8 +182,6 @@ case WLC_INPUT_EVENT_BUTTON: { - const struct wlc_size resolution = (output ? output->resolution : wlc_size_zero); - const struct wlc_pointer_origin pos = { chck_clamp(seat->pointer.pos.x, 0, resolution.w), chck_clamp(seat->pointer.pos.y, 0, resolution.h), @@ -203,8 +200,6 @@ case WLC_INPUT_EVENT_TOUCH: { - const struct wlc_size resolution = (output ? output->resolution : wlc_size_zero); - struct wlc_point pos = {0, 0}; if (ev->touch.x && ev->touch.y && ev->touch.internal) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/view.c new/wlc-0.0.5/src/compositor/view.c --- old/wlc-0.0.3/src/compositor/view.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/view.c 2016-08-02 19:57:11.000000000 +0200 @@ -175,13 +175,6 @@ } 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 !is_x11_view(view); } void @@ -194,19 +187,21 @@ 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) { + if (view->xdg_surface && !wlc_size_equals(&view->surface_commit.visible.size, &wlc_size_zero)) { // 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; + struct wlc_geometry v = view->surface_commit.visible; + v.origin.x = chck_clamp32(v.origin.x, 0, surface->size.w); + v.origin.y = chck_clamp32(v.origin.y, 0, surface->size.h); + v.size.w = chck_clampu32(surface->size.w - v.size.w, 0, surface->size.w); + v.size.h = chck_clampu32(surface->size.h - v.size.h, 0, surface->size.h); + + assert(surface->size.w > 0 && surface->size.h > 0); + const float wa = (float)out_bounds->size.w / surface->size.w, ha = (float)out_bounds->size.h / surface->size.h; + + out_bounds->origin.x -= v.origin.x * wa; + out_bounds->origin.y -= v.origin.y * ha; + out_bounds->size.w += v.size.w * wa; + out_bounds->size.h += v.size.h * ha; } // Make sure bounds is never 0x0 w/h @@ -221,16 +216,15 @@ out_visible->size = surface->size; // Scale visible area retaining aspect - struct wlc_size ssize; - wlc_size_max(&surface->size, &(struct wlc_size){ 1, 1 }, &ssize); + assert(surface->size.w > 0 && surface->size.h > 0); const float ba = (float)out_bounds->size.w / (float)out_bounds->size.h; - const float sa = (float)ssize.w / (float)ssize.h; + const float sa = (float)surface->size.w / (float)surface->size.h; if (ba < sa) { - out_visible->size.w *= (float)out_bounds->size.w / ssize.w; - out_visible->size.h *= (float)out_bounds->size.w / ssize.w; + out_visible->size.w *= (float)out_bounds->size.w / surface->size.w; + out_visible->size.h *= (float)out_bounds->size.w / surface->size.w; } else { - out_visible->size.w *= (float)out_bounds->size.h / ssize.h; - out_visible->size.h *= (float)out_bounds->size.h / ssize.h; + out_visible->size.w *= (float)out_bounds->size.h / surface->size.h; + out_visible->size.h *= (float)out_bounds->size.h / surface->size.h; } // Center visible area @@ -250,32 +244,25 @@ wlc_view_get_opaque(struct wlc_view *view, struct wlc_geometry *out_opaque) { assert(view && out_opaque); - memcpy(out_opaque, &wlc_geometry_zero, sizeof(struct wlc_geometry)); - - struct wlc_surface *surface; - if (!(surface = convert_from_wlc_resource(view->surface, "surface"))) - return true; struct wlc_geometry b, v; wlc_view_get_bounds(view, &b, &v); + return wlc_surface_get_opaque(convert_from_wlc_resource(view->surface, "surface"), &v.origin, out_opaque); +} - const bool opaque = ((surface->pending.opaque.extents.x1 + surface->pending.opaque.extents.y1 + surface->pending.opaque.extents.x2 + surface->pending.opaque.extents.y2) > 0); +void +wlc_view_get_input(struct wlc_view *view, struct wlc_geometry *out_input) +{ + assert(view && out_input); + struct wlc_geometry b, v; + wlc_view_get_bounds(view, &b, &v); - if (opaque && (wlc_size_equals(&surface->size, &b.size) || wlc_geometry_equals(&v, &b))) { - // Only ran when we don't draw black borders behind the view - const float miw = chck_minf(surface->size.w, b.size.w), maw = chck_maxf(surface->size.w, b.size.w); - const float mih = chck_minf(surface->size.h, b.size.h), mah = chck_maxf(surface->size.h, b.size.h); - const int32_t dw = surface->size.w - (surface->pending.opaque.extents.x2 - surface->pending.opaque.extents.x1); - const int32_t dh = surface->size.h - (surface->pending.opaque.extents.y2 - surface->pending.opaque.extents.y1); - b.origin.x += surface->pending.opaque.extents.x1 * miw / maw; - b.origin.y += surface->pending.opaque.extents.y1 * mih / mah; - b.size.w -= dw * miw / maw; - b.size.h -= dh * mih / mah; - // printf("O: %ux%u+%d,%d\n", b.size.w, b.size.h, b.origin.x, b.origin.y); + if (is_x11_view(view)) { + *out_input = v; + return; } - memcpy(out_opaque, &b, sizeof(b)); - return opaque; + wlc_surface_get_input(convert_from_wlc_resource(view->surface, "surface"), &v.origin, out_input); } bool @@ -459,6 +446,16 @@ } void +wlc_view_set_pid_ptr(struct wlc_view *view, pid_t pid) +{ + if (!view || view->data.pid == pid) + return; + + view->data.pid = pid; + WLC_INTERFACE_EMIT(view.properties_updated, convert_to_wlc_handle(view), WLC_BIT_PROPERTY_PID); +} + +void wlc_view_close_ptr(struct wlc_view *view) { if (!view) @@ -668,6 +665,22 @@ return get_cstr(convert_from_wlc_handle(view, "view"), offsetof(struct wlc_view, data.app_id)); } +WLC_API pid_t +wlc_view_get_pid(wlc_handle handle) +{ + struct wlc_view *view; + if(!(view = convert_from_wlc_handle(handle, "view"))) + return 0; + + if (is_x11_view(view)) { + return view->data.pid; + } else { + pid_t pid; + wl_client_get_credentials(wlc_view_get_client_ptr(view), &pid, NULL, NULL); + return pid; + } +} + void wlc_view_release(struct wlc_view *view) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/compositor/view.h new/wlc-0.0.5/src/compositor/view.h --- old/wlc-0.0.3/src/compositor/view.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/compositor/view.h 2016-08-02 19:57:11.000000000 +0200 @@ -2,6 +2,7 @@ #define _WLC_VIEW_H_ #include <stdbool.h> +#include <sys/types.h> #include <wlc/geometry.h> #include <wayland-util.h> #include <chck/pool/pool.h> @@ -47,6 +48,7 @@ struct chck_string app_id; struct chck_string title; struct chck_string _class; + pid_t pid; enum wl_shell_surface_fullscreen_method fullscreen_mode; bool minimized; } data; @@ -72,6 +74,7 @@ WLC_NONULL void wlc_view_ack_surface_attach(struct wlc_view *view, struct wlc_surface *surface); WLC_NONULLV(1,2) void wlc_view_get_bounds(struct wlc_view *view, struct wlc_geometry *out_bounds, struct wlc_geometry *out_visible); WLC_NONULL bool wlc_view_get_opaque(struct wlc_view *view, struct wlc_geometry *out_opaque); +WLC_NONULL void wlc_view_get_input(struct wlc_view *view, struct wlc_geometry *out_input); WLC_NONULL bool wlc_view_request_geometry(struct wlc_view *view, const struct wlc_geometry *r); bool wlc_view_request_state(struct wlc_view *view, enum wlc_view_state_bit state, bool toggle); void wlc_view_set_surface(struct wlc_view *view, struct wlc_surface *surface); @@ -98,5 +101,6 @@ void wlc_view_set_title_ptr(struct wlc_view *view, const char *title, size_t length); void wlc_view_set_class_ptr(struct wlc_view *view, const char *class_, size_t length); void wlc_view_set_app_id_ptr(struct wlc_view *view, const char *app_id); +void wlc_view_set_pid_ptr(struct wlc_view *view, pid_t pid); #endif /* _WLC_VIEW_H_ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/backend/backend.c new/wlc-0.0.5/src/platform/backend/backend.c --- old/wlc-0.0.3/src/platform/backend/backend.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/backend/backend.c 2016-08-02 19:57:11.000000000 +0200 @@ -3,10 +3,11 @@ #include <assert.h> #include "internal.h" #include "backend.h" +#include "drm.h" + #ifdef ENABLE_X11_BACKEND -#include "x11.h" +# include "x11.h" #endif -#include "drm.h" bool wlc_backend_surface(struct wlc_backend_surface *surface, void (*destructor)(struct wlc_backend_surface*), size_t internal_size) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/backend/backend.h new/wlc-0.0.5/src/platform/backend/backend.h --- old/wlc-0.0.3/src/platform/backend/backend.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/backend/backend.h 2016-08-02 19:57:11.000000000 +0200 @@ -5,7 +5,6 @@ #include <stdbool.h> #include "EGL/egl.h" -struct wlc_output; struct chck_pool; struct wlc_backend_surface { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/backend/drm.c new/wlc-0.0.5/src/platform/backend/drm.c --- old/wlc-0.0.3/src/platform/backend/drm.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/backend/drm.c 2016-08-02 19:57:11.000000000 +0200 @@ -349,7 +349,6 @@ info->info.physical_width = connector->mmWidth; info->info.physical_height = connector->mmHeight; info->info.subpixel = connector->subpixel; - info->info.scale = 1; // weston gets this from config? info->info.connector_id = connector->connector_type_id; info->info.connector = wlc_connector_for_drm_connector(connector->connector_type); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/backend/x11.c new/wlc-0.0.5/src/platform/backend/x11.c --- old/wlc-0.0.3/src/platform/backend/x11.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/backend/x11.c 2016-08-02 19:57:11.000000000 +0200 @@ -183,7 +183,7 @@ struct wlc_output *output; if ((output = output_for_window(&compositor->outputs.pool, ev->window))) { output->mode = (struct wlc_size){ ev->width, ev->height }; - wlc_output_set_resolution_ptr(output, &output->mode); // XXX: make a request? + wlc_output_set_resolution_ptr(output, &output->mode, output->scale); // XXX: make a request? } } break; @@ -226,6 +226,11 @@ case XCB_BUTTON_PRESS: { xcb_button_press_event_t *xev = (xcb_button_press_event_t*)event; + + // do not send scroll up / down events + if (xev->detail >= 4 && xev->detail <= 7) + break; + struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_BUTTON; ev.time = xev->time; @@ -307,7 +312,6 @@ wlc_output_information(info); chck_string_set_cstr(&info->make, "Xorg", false); chck_string_set_cstr(&info->model, "X11 Window", false); - info->scale = 1; info->connector = WLC_CONNECTOR_WLC; info->connector_id = id; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/render/gles2.c new/wlc-0.0.5/src/platform/render/gles2.c --- old/wlc-0.0.3/src/platform/render/gles2.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/render/gles2.c 2016-08-02 19:57:11.000000000 +0200 @@ -18,6 +18,7 @@ #include "resources/types/buffer.h" static bool DRAW_OPAQUE = false; +static bool DRAW_INPUT = false; static const GLubyte cursor_palette[]; @@ -42,6 +43,8 @@ enum { TEXTURE_BLACK, + TEXTURE_RED, + TEXTURE_BLUE, TEXTURE_CURSOR, TEXTURE_FAKEFB, TEXTURE_LAST @@ -72,10 +75,13 @@ } programs[PROGRAM_LAST]; struct wlc_size resolution, mode; + uint32_t scale; + GLuint textures[TEXTURE_LAST]; GLuint clear_fbo; GLenum internal_format; GLenum preferred_type; + bool native_resolution; bool fakefb_dirty; struct { @@ -379,6 +385,8 @@ const void *data; } images[TEXTURE_LAST] = { { GL_LUMINANCE, 1, 1, GL_UNSIGNED_BYTE, NULL }, // TEXTURE_BLACK + { GL_RGB, 1, 1, GL_UNSIGNED_BYTE, (GLubyte[]){255, 0, 0} }, // TEXTURE_RED + { GL_RGB, 1, 1, GL_UNSIGNED_BYTE, (GLubyte[]){0, 0, 255} }, // TEXTURE_BLUE { GL_LUMINANCE, 14, 14, GL_UNSIGNED_BYTE, cursor_palette }, // TEXTURE_CURSOR { GL_RGBA, 0, 0, GL_UNSIGNED_BYTE, NULL }, // TEXTURE_FAKEFB }; @@ -417,9 +425,9 @@ } static void -resolution(struct ctx *context, const struct wlc_size *mode, const struct wlc_size *resolution) +resolution(struct ctx *context, const struct wlc_size *mode, const struct wlc_size *resolution, uint32_t scale) { - assert(context && resolution); + assert(context && resolution && scale > 0); if (!wlc_size_equals(&context->resolution, resolution)) { for (GLuint i = 0; i < PROGRAM_LAST; ++i) { @@ -437,6 +445,10 @@ GL_CALL(glViewport(0, 0, mode->w, mode->h)); context->mode = *mode; } + + struct wlc_size virtual = { .w = mode->w / (float)scale, .h = mode->h / (float)scale }; + context->native_resolution = wlc_size_equals(resolution, &virtual); + context->scale = scale; } static void @@ -673,7 +685,7 @@ GL_CALL(glActiveTexture(GL_TEXTURE0 + i)); GL_CALL(glBindTexture(GL_TEXTURE_2D, textures[i])); - if (settings->filter || !wlc_size_equals(&context->resolution, &context->mode)) { + if (settings->filter || !context->native_resolution) { GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); } else { @@ -694,6 +706,9 @@ const struct wlc_geometry *g = geometry; + assert(surface->commit.scale >= 1); + settings->filter = ((uint32_t)surface->commit.scale != context->scale); + if (!wlc_size_equals(&surface->size, &geometry->size)) { if (wlc_geometry_equals(&settings->visible, geometry)) { settings->filter = true; @@ -717,6 +732,22 @@ settings.program = (enum program_type)surface->format; settings.visible = *geometry; surface_paint_internal(context, surface, geometry, &settings); + + if (DRAW_OPAQUE) { + wlc_surface_get_opaque(surface, &geometry->origin, &settings.visible); + settings.program = PROGRAM_RGB; + GL_CALL(glBlendFunc(GL_ONE, GL_DST_COLOR)); + texture_paint(context, &context->textures[TEXTURE_RED], 1, &settings.visible, &settings); + GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + } + + if (DRAW_INPUT) { + wlc_surface_get_input(surface, &geometry->origin, &settings.visible); + settings.program = PROGRAM_RGB; + GL_CALL(glBlendFunc(GL_ONE, GL_DST_COLOR)); + texture_paint(context, &context->textures[TEXTURE_BLUE], 1, &settings.visible, &settings); + GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + } } static void @@ -737,11 +768,18 @@ surface_paint_internal(context, surface, &geometry, &settings); if (DRAW_OPAQUE) { - wlc_view_get_opaque(view, &geometry); - settings.visible = geometry; - settings.program = PROGRAM_CURSOR; + wlc_view_get_opaque(view, &settings.visible); + settings.program = PROGRAM_RGB; + GL_CALL(glBlendFunc(GL_ONE, GL_DST_COLOR)); + texture_paint(context, &context->textures[TEXTURE_RED], 1, &settings.visible, &settings); + GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + } + + if (DRAW_INPUT) { + wlc_view_get_input(view, &settings.visible); + settings.program = PROGRAM_RGB; GL_CALL(glBlendFunc(GL_ONE, GL_DST_COLOR)); - texture_paint(context, &context->textures[TEXTURE_BLACK], 1, &geometry, &settings); + texture_paint(context, &context->textures[TEXTURE_BLUE], 1, &settings.visible, &settings); GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); } } @@ -791,7 +829,7 @@ (void)context; assert(context && geometry && out_geometry && out_data); struct wlc_geometry g = *geometry; - clamp_to_bounds(&g, &context->resolution); + clamp_to_bounds(&g, &context->mode); GL_CALL(glReadPixels(g.origin.x, g.origin.y, g.size.w, g.size.h, format_map[format].format, format_map[format].type, out_data)); *out_geometry = g; } @@ -802,7 +840,7 @@ (void)context; assert(context && geometry && data); struct wlc_geometry g = *geometry; - clamp_to_bounds(&g, &context->resolution); + clamp_to_bounds(&g, &context->mode); GL_CALL(glBindTexture(GL_TEXTURE_2D, context->textures[TEXTURE_FAKEFB])); GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, g.origin.x, g.origin.y, g.size.w, g.size.h, format_map[format].format, format_map[format].type, data)); context->fakefb_dirty = true; @@ -868,6 +906,7 @@ api->clear = clear; chck_cstr_to_bool(getenv("WLC_DRAW_OPAQUE"), &DRAW_OPAQUE); + chck_cstr_to_bool(getenv("WLC_DRAW_INPUT"), &DRAW_INPUT); wlc_log(WLC_LOG_INFO, "GLES2 renderer initialized"); return ctx; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/render/render.c new/wlc-0.0.5/src/platform/render/render.c --- old/wlc-0.0.3/src/platform/render/render.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/render/render.c 2016-08-02 19:57:11.000000000 +0200 @@ -6,14 +6,14 @@ #include "gles2.h" void -wlc_render_resolution(struct wlc_render *render, struct wlc_context *bound, const struct wlc_size *mode, const struct wlc_size *resolution) +wlc_render_resolution(struct wlc_render *render, struct wlc_context *bound, const struct wlc_size *mode, const struct wlc_size *resolution, uint32_t scale) { assert(render && bound && mode && resolution); if (!render->api.resolution || !wlc_context_bind(bound)) return; - render->api.resolution(render->render, mode, resolution); + render->api.resolution(render->render, mode, resolution, scale); } void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/platform/render/render.h new/wlc-0.0.5/src/platform/render/render.h --- old/wlc-0.0.3/src/platform/render/render.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/platform/render/render.h 2016-08-02 19:57:11.000000000 +0200 @@ -19,7 +19,7 @@ struct wlc_render_api { enum wlc_renderer renderer_type; WLC_NONULL void (*terminate)(struct ctx *render); - WLC_NONULL void (*resolution)(struct ctx *render, const struct wlc_size *mode, const struct wlc_size *resolution); + WLC_NONULL void (*resolution)(struct ctx *render, const struct wlc_size *mode, const struct wlc_size *resolution, uint32_t scale); WLC_NONULL void (*surface_destroy)(struct ctx *render, struct wlc_context *bound, struct wlc_surface *surface); WLC_NONULLV(1,2,3) bool (*surface_attach)(struct ctx *render, struct wlc_context *bound, struct wlc_surface *surface, struct wlc_buffer *buffer); WLC_NONULL void (*view_paint)(struct ctx *render, struct wlc_view *view); @@ -36,7 +36,7 @@ struct wlc_render_api api; }; -WLC_NONULL void wlc_render_resolution(struct wlc_render *render, struct wlc_context *bound, const struct wlc_size *mode, const struct wlc_size *resolution); +WLC_NONULL void wlc_render_resolution(struct wlc_render *render, struct wlc_context *bound, const struct wlc_size *mode, const struct wlc_size *resolution, uint32_t scale); WLC_NONULL void wlc_render_surface_destroy(struct wlc_render *render, struct wlc_context *bound, struct wlc_surface *surface); WLC_NONULLV(1,2,3) bool wlc_render_surface_attach(struct wlc_render *render, struct wlc_context *bound, struct wlc_surface *surface, struct wlc_buffer *buffer); WLC_NONULL void wlc_render_view_paint(struct wlc_render *render, struct wlc_context *bound, struct wlc_view *view); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/resources/types/surface.c new/wlc-0.0.5/src/resources/types/surface.c --- old/wlc-0.0.3/src/resources/types/surface.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/resources/types/surface.c 2016-08-02 19:57:11.000000000 +0200 @@ -10,6 +10,7 @@ #include "macros.h" #include "compositor/output.h" #include "compositor/view.h" +#include <chck/math/math.h> static void surface_attach(struct wlc_surface *surface, struct wlc_buffer *buffer) @@ -46,14 +47,7 @@ static void commit_state(struct wlc_surface *surface, struct wlc_surface_state *pending, struct wlc_surface_state *out) { - if (pending->attached) { - surface_attach(surface, convert_from_wlc_resource(pending->buffer, "buffer")); - pending->attached = false; - } - - state_set_buffer(out, convert_from_wlc_resource(pending->buffer, "buffer")); - state_set_buffer(pending, NULL); - + out->scale = chck_max32(pending->scale, 1); pending->offset = wlc_point_zero; wlc_resource *r; @@ -75,6 +69,25 @@ pixman_region32_fini(&opaque); pixman_region32_intersect_rect(&out->input, &pending->input, 0, 0, surface->size.w, surface->size.h); + + if (pending->attached) { + surface_attach(surface, convert_from_wlc_resource(pending->buffer, "buffer")); + pending->attached = false; + } + + state_set_buffer(out, convert_from_wlc_resource(pending->buffer, "buffer")); + state_set_buffer(pending, NULL); +} + +static void +init_state(struct wlc_surface_state *state) +{ + assert(state); + pixman_region32_init_rect(&state->opaque, 0, 0, 0, 0); + pixman_region32_init_rect(&state->damage, 0, 0, 0, 0); + pixman_region32_init_rect(&state->input, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); + state->scale = 1; + state->subsurface_position = (struct wlc_point){0, 0}; } static void @@ -252,7 +265,70 @@ return; } - surface->pending.scale = 1; + surface->pending.scale = scale; +} + +bool +wlc_surface_get_opaque(struct wlc_surface *surface, const struct wlc_point *offset, struct wlc_geometry *out_opaque) +{ + *out_opaque = wlc_geometry_zero; + + if (!surface) + return false; + + assert(offset && out_opaque); + const bool opaque = ((surface->commit.opaque.extents.x1 + surface->commit.opaque.extents.y1 + surface->commit.opaque.extents.x2 + surface->commit.opaque.extents.y2) > 0); + + if (opaque) { + struct wlc_geometry o = { + .origin = { + chck_min32(surface->commit.opaque.extents.x1, surface->size.w), + chck_min32(surface->commit.opaque.extents.y1, surface->size.h), + }, + }; + + o.size.w = chck_clamp32(surface->commit.opaque.extents.x2, o.origin.x, surface->size.w), + o.size.h = chck_clamp32(surface->commit.opaque.extents.y2, o.origin.y, surface->size.h), + assert((int32_t)o.size.w >= o.origin.x && (int32_t)o.size.h >= o.origin.y); + + struct wlc_geometry v; + v.origin.x = offset->x + o.origin.x * surface->coordinate_transform.w; + v.origin.y = offset->y + o.origin.y * surface->coordinate_transform.h; + v.size.w = (o.size.w - o.origin.x) * surface->coordinate_transform.w; + v.size.h = (o.size.h - o.origin.y) * surface->coordinate_transform.h; + *out_opaque = v; + } else { + struct wlc_geometry v = { + .origin = *offset, + .size = { + .w = surface->size.w * surface->coordinate_transform.w, + .h = surface->size.h * surface->coordinate_transform.h, + } + }; + *out_opaque = v; + } + + return opaque; +} + +void +wlc_surface_get_input(struct wlc_surface *surface, const struct wlc_point *offset, struct wlc_geometry *out_input) +{ + *out_input = wlc_geometry_zero; + + if (!surface) + return; + + assert(offset && out_input); + assert(surface->commit.input.extents.x2 >= surface->commit.input.extents.x1); + assert(surface->commit.input.extents.y2 >= surface->commit.input.extents.y1); + + struct wlc_geometry v; + v.origin.x = offset->x + surface->commit.input.extents.x1 * surface->coordinate_transform.w; + v.origin.y = offset->y + surface->commit.input.extents.y1 * surface->coordinate_transform.h; + v.size.w = (surface->commit.input.extents.x2 - surface->commit.input.extents.x1) * surface->coordinate_transform.w; + v.size.h = (surface->commit.input.extents.y2 - surface->commit.input.extents.y1) * surface->coordinate_transform.h; + *out_input = v; } struct wlc_buffer* @@ -287,17 +363,25 @@ if (buffer) size = buffer->size; + wlc_size_max(&size, &size, &(struct wlc_size){1, 1}); + size.w /= surface->commit.scale; + size.h /= surface->commit.scale; surface->size = size; - if (surface->view) { - struct wlc_view *view = convert_from_wlc_handle(surface->view, "view"); + struct wlc_view *view; + if (surface->view && (view = convert_from_wlc_handle(surface->view, "view"))) { struct wlc_geometry g, area; - - struct wlc_size ssize = { 1, 1 }; - wlc_size_max(&ssize, &surface->size, &ssize); wlc_view_get_bounds(view, &g, &area); - surface->coordinate_transform.w = (float)(area.size.w) / ssize.w; - surface->coordinate_transform.h = (float)(area.size.h) / ssize.h; + surface->coordinate_transform.w = (float)(area.size.w) / size.w; + surface->coordinate_transform.h = (float)(area.size.h) / size.h; + } else { + surface->coordinate_transform = (struct wlc_coordinate_scale) {1, 1}; + } + + struct wlc_surface *p; + if ((p = convert_from_wlc_resource(surface->parent, "surface"))) { + surface->coordinate_transform.w *= p->coordinate_transform.w; + surface->coordinate_transform.h *= p->coordinate_transform.h; } surface->commit.attached = (buffer ? true : false); @@ -391,10 +475,10 @@ !chck_iter_pool(&surface->subsurface_list, 4, 0, sizeof(wlc_resource))) goto fail; - surface->pending.subsurface_position = (struct wlc_point){0, 0}; - surface->coordinate_transform = (struct wlc_coordinate_scale) {1, 1}; + init_state(&surface->pending); + init_state(&surface->commit); + surface->coordinate_transform = (struct wlc_coordinate_scale){1, 1}; surface->parent_synchronized = false; - return true; fail: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/resources/types/surface.h new/wlc-0.0.5/src/resources/types/surface.h --- old/wlc-0.0.3/src/resources/types/surface.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/resources/types/surface.h 2016-08-02 19:57:11.000000000 +0200 @@ -50,7 +50,7 @@ wlc_handle parent_view; /* Current output the surface is attached to */ - wlc_resource output; + wlc_handle output; /** * "Texture" as we use OpenGL terminology, but can be id to anything. @@ -69,6 +69,8 @@ bool synchronized, parent_synchronized; }; +WLC_NONULLV(2,3) bool wlc_surface_get_opaque(struct wlc_surface *surface, const struct wlc_point *offset, struct wlc_geometry *out_opaque); +WLC_NONULLV(2,3) void wlc_surface_get_input(struct wlc_surface *surface, const struct wlc_point *offset, struct wlc_geometry *out_input); struct wlc_buffer* wlc_surface_get_buffer(struct wlc_surface *surface); void wlc_surface_attach_to_view(struct wlc_surface *surface, struct wlc_view *view); bool wlc_surface_attach_to_output(struct wlc_surface *surface, struct wlc_output *output, struct wlc_buffer *buffer); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/xwayland/xwm.c new/wlc-0.0.5/src/xwayland/xwm.c --- old/wlc-0.0.3/src/xwayland/xwm.c 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/xwayland/xwm.c 2016-08-02 19:57:11.000000000 +0200 @@ -181,7 +181,7 @@ } static void -read_properties(struct wlc_xwm *xwm, struct wlc_x11_window *win) +read_properties(struct wlc_xwm *xwm, struct wlc_x11_window *win, const xcb_atom_t *props, size_t nmemb) { assert(win); @@ -189,112 +189,99 @@ if (!(view = view_for_window(win))) return; -#define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0 -#define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1 -#define TYPE_NET_WM_STATE XCB_ATOM_CUT_BUFFER2 -#define TYPE_WM_NORMAL_HINTS XCB_ATOM_CUT_BUFFER3 - - const struct { - xcb_atom_t atom; - xcb_atom_t type; - } props[] = { - { XCB_ATOM_WM_CLASS, XCB_ATOM_STRING }, - { XCB_ATOM_WM_NAME, XCB_ATOM_STRING }, - { XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW }, - { x11.atoms[WM_PROTOCOLS], TYPE_WM_PROTOCOLS }, - { x11.atoms[WM_NORMAL_HINTS], TYPE_WM_NORMAL_HINTS }, - { x11.atoms[NET_WM_STATE], TYPE_NET_WM_STATE }, - { x11.atoms[NET_WM_WINDOW_TYPE], XCB_ATOM_ATOM }, - { x11.atoms[NET_WM_NAME], XCB_ATOM_STRING }, - { x11.atoms[NET_WM_PID], XCB_ATOM_CARDINAL }, - { x11.atoms[MOTIF_WM_HINTS], TYPE_MOTIF_WM_HINTS }, - }; - xcb_get_property_cookie_t *cookies; - if (!(cookies = chck_calloc_of(LENGTH(props), sizeof(xcb_get_property_cookie_t)))) + if (!(cookies = chck_calloc_of(nmemb, sizeof(xcb_get_property_cookie_t)))) return; - for (uint32_t i = 0; i < LENGTH(props); ++i) - cookies[i] = xcb_get_property(x11.connection, 0, win->id, props[i].atom, XCB_ATOM_ANY, 0, 2048); + 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 < LENGTH(props); ++i) { + 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_NONE) { - free(reply); - continue; - } - - switch (props[i].type) { - case XCB_ATOM_STRING: - // Class && Name - if (props[i].atom == XCB_ATOM_WM_CLASS) { - wlc_view_set_class_ptr(view, xcb_get_property_value(reply), xcb_get_property_value_length(reply)); - } else if (props[i].atom == XCB_ATOM_WM_NAME) { + 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; } - break; - case XCB_ATOM_WINDOW: - { - // Transient - xcb_window_t *xid = xcb_get_property_value(reply); - set_parent(xwm, win, *xid); + 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); } - break; - case XCB_ATOM_CARDINAL: - // PID - break; - case 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); + } 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_view_set_pid_ptr(view, *(pid_t *)xcb_get_property_value(reply)); + 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); } - break; - case TYPE_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, "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; } - break; - case TYPE_WM_NORMAL_HINTS: - break; - case TYPE_NET_WM_STATE: - handle_state(win, xcb_get_property_value(reply), reply->value_len, NET_WM_STATE_ADD); - break; - case TYPE_MOTIF_WM_HINTS: - // Motif hints - break; + 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); +} -#undef TYPE_WM_PROTOCOLS -#undef TYPE_MOTIF_WM_HINTS -#undef TYPE_NET_WM_STATE -#undef TYPE_WM_NORMAL_HINTS +static void +get_properties(struct wlc_xwm *xwm, struct wlc_x11_window *win) +{ + const xcb_atom_t props[] = { + XCB_ATOM_WM_CLASS, + XCB_ATOM_WM_NAME, + XCB_ATOM_WM_TRANSIENT_FOR, + x11.atoms[WM_PROTOCOLS], + x11.atoms[WM_NORMAL_HINTS], + x11.atoms[NET_WM_STATE], + x11.atoms[NET_WM_WINDOW_TYPE], + x11.atoms[NET_WM_NAME], + x11.atoms[NET_WM_PID], + x11.atoms[MOTIF_WM_HINTS] + }; + + read_properties(xwm, win, props, LENGTH(props)); } static void @@ -372,7 +359,7 @@ view->x11.paired = true; wlc_view_set_type_ptr(view, WLC_BIT_OVERRIDE_REDIRECT, view->x11.override_redirect); - read_properties(xwm, &view->x11); + get_properties(xwm, &view->x11); if (!wlc_geometry_equals(&geometry, &wlc_geometry_zero)) wlc_view_set_geometry_ptr(view, 0, &geometry); @@ -485,7 +472,7 @@ { assert(win); - if (!x11.connection || !win->id) + if (!x11.connection || !win->id || win->override_redirect) return false; if (active) { @@ -612,7 +599,7 @@ wlc_dlog(WLC_DBG_XWM, "XCB_PROPERTY_NOTIFY (%u)", ev->window); struct wlc_x11_window *win; if ((win = paired_for_id(xwm, ev->window)) || (win = unpaired_for_id(xwm, ev->window))) - read_properties(xwm, win); + read_properties(xwm, win, &ev->atom, 1); } break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wlc-0.0.3/src/xwayland/xwm.h new/wlc-0.0.5/src/xwayland/xwm.h --- old/wlc-0.0.3/src/xwayland/xwm.h 2016-05-22 21:15:27.000000000 +0200 +++ new/wlc-0.0.5/src/xwayland/xwm.h 2016-08-02 19:57:11.000000000 +0200 @@ -14,6 +14,7 @@ uint32_t id; // xcb_window_t uint32_t surface_id; bool override_redirect; + bool has_utf8_title; bool has_delete_window; bool has_alpha; bool hidden; // HACK: used by output.c to hide invisible windows