/** * Synchronously modifies the region. * @param damage The damage object to destroy. * @param repair The repair region. * @param parts The parts region. * * Synchronously modifies the regions in the following manner: * If @p repair is @c XCB_NONE: * 1) parts = damage * 2) damage = <empty> * Otherwise: * 1) parts = damage INTERSECT repair * 2) damage = damage - parts * 3) Generate DamageNotify for remaining damage areas * @ingroup Ecore_X_Damage_Group */ EAPI void ecore_x_damage_subtract(Ecore_X_Damage damage, Ecore_X_Region repair, Ecore_X_Region parts) { #ifdef ECORE_XCB_DAMAGE xcb_damage_subtract(_ecore_xcb_conn, damage, repair, parts); #endif /* ECORE_XCB_DAMAGE */ } /* ecore_x_damage_subtract */
bool FdoSelectionManager::nativeEventFilter(const QByteArray& eventType, void* message, long int* result) { Q_UNUSED(result); if (eventType != "xcb_generic_event_t") { return false; } xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message); auto responseType = XCB_EVENT_RESPONSE_TYPE(ev); if (responseType == XCB_CLIENT_MESSAGE) { auto ce = reinterpret_cast<xcb_client_message_event_t *>(ev); if (ce->type == Xcb::atoms->opcodeAtom) { switch (ce->data.data32[1]) { case SYSTEM_TRAY_REQUEST_DOCK: dock(ce->data.data32[2]); return true; } } } else if (responseType == XCB_UNMAP_NOTIFY) { auto unmappedWId = reinterpret_cast<xcb_unmap_notify_event_t *>(ev)->window; if (m_proxies[unmappedWId]) { undock(unmappedWId); } } else if (responseType == m_damageEventBase + XCB_DAMAGE_NOTIFY) { auto damagedWId = reinterpret_cast<xcb_damage_notify_event_t *>(ev)->drawable; auto sniProx = m_proxies[damagedWId]; Q_ASSERT(sniProx); if(sniProx) { sniProx->update(); xcb_damage_subtract(QX11Info::connection(), m_damageWatches[damagedWId], XCB_NONE, XCB_NONE); } } return false; }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "X11 connection broke, did your server terminate?\n"); while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t *)event; /* Ignore errors when damage report is about destroyed window * or damage object is created for already destroyed window */ if (error->major_code == dam_ext_data->major_opcode && (error->minor_code == XCB_DAMAGE_SUBTRACT || error->minor_code == XCB_DAMAGE_CREATE)) { free(event); continue; } if (debug_mode) fprintf(stderr, "X11 Error received! sequence 0x%x, error_code " "= %d, major = 0x%x, minor = 0x%x\n", error->sequence, error->error_code, error->major_code, error->minor_code); free(event); continue; } if (fuzzy && event->response_type == dam_ext_data->first_event + XCB_DAMAGE_NOTIFY) { xcb_damage_notify_event_t *ev = (xcb_damage_notify_event_t *)event; xcb_damage_subtract(conn, ev->damage, XCB_NONE, XCB_NONE); redraw_screen(); } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t *)event); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify( conn, (xcb_visibility_notify_event_t *)event); break; case XCB_MAP_NOTIFY: handle_map_notify((xcb_map_notify_event_t *)event); break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }
void * run_event_loop(void *thread_arg_struct) { _connection_data *conn_data; xcwm_context_t *context; xcb_connection_t *event_conn; xcb_generic_event_t *evt; xcwm_event_t return_evt; xcwm_event_cb_t callback_ptr; conn_data = thread_arg_struct; context = conn_data->context; event_conn = context->conn; callback_ptr = conn_data->callback; free(thread_arg_struct); _xcwm_windows_adopt(context, callback_ptr); /* Start the event loop, and flush if first */ xcb_flush(event_conn); while ((evt = xcb_wait_for_event(event_conn))) { uint8_t response_type = evt->response_type & ~0x80; if (response_type == context->damage_event_mask) { xcb_damage_notify_event_t *dmgevnt = (xcb_damage_notify_event_t *)evt; /* printf("damage %d,%d @ %d,%d reported against window 0x%08x\n", */ /* dmgevnt->area.width, dmgevnt->area.height, dmgevnt->area.x, dmgevnt->area.y, */ /* dmgevnt->drawable); */ xcwm_window_t *window = _xcwm_get_window_node_by_window_id(dmgevnt->drawable); return_evt.event_type = XCWM_EVENT_WINDOW_DAMAGE; return_evt.window = window; if (!window) { printf("damage reported against unknown window 0x%08x\n", dmgevnt->drawable); continue; } /* Increase the damaged area of window if new damage is * larger than current. */ xcwm_event_get_thread_lock(); /* Initial damage events for override-redirect windows are * reported relative to the root window, subsequent events * are relative to the window itself. We also catch cases * where the damage area is larger than the bounds of the * window. */ if (window->initial_damage == 1 || (dmgevnt->area.width > window->bounds.width) || (dmgevnt->area.height > window->bounds.height) ) { xcb_xfixes_region_t region = xcb_generate_id(window->context->conn); xcb_rectangle_t rect; /* printf("initial damage on window 0x%08x\n", dmgevnt->drawable); */ /* Remove the damage */ xcb_xfixes_create_region(window->context->conn, region, 1, &dmgevnt->area); xcb_damage_subtract(window->context->conn, window->damage, region, XCB_NONE); /* Add new damage area for entire window */ rect.x = 0; rect.y = 0; rect.width = window->bounds.width; rect.height = window->bounds.height; xcb_xfixes_set_region(window->context->conn, region, 1, &rect); xcb_damage_add(window->context->conn, window->window_id, region); window->initial_damage = 0; xcb_xfixes_destroy_region(window->context->conn, region); xcwm_event_release_thread_lock(); continue; } window->dmg_bounds.x = dmgevnt->area.x; window->dmg_bounds.y = dmgevnt->area.y; window->dmg_bounds.width = dmgevnt->area.width; window->dmg_bounds.height = dmgevnt->area.height; xcwm_event_release_thread_lock(); callback_ptr(&return_evt); } else if (response_type == context->shape_event) { xcb_shape_notify_event_t *shapeevnt = (xcb_shape_notify_event_t *)evt; if (shapeevnt->shape_kind == XCB_SHAPE_SK_BOUNDING) { xcwm_window_t *window = _xcwm_get_window_node_by_window_id(shapeevnt->affected_window); _xcwm_window_set_shape(window, shapeevnt->shaped); return_evt.event_type = XCWM_EVENT_WINDOW_SHAPE; return_evt.window = window; callback_ptr(&return_evt); } } else if (response_type == context->fixes_event_base + XCB_XFIXES_CURSOR_NOTIFY) { /* xcb_xfixes_cursor_notify_event_t *cursorevnt = */ /* (xcb_xfixes_cursor_notify_event_t *)evt; */ return_evt.event_type = XCWM_EVENT_CURSOR; return_evt.window = NULL; callback_ptr(&return_evt); } else { switch (response_type) { case 0: { /* Error case. Something very bad has happened. Spit * out some hopefully useful information and then * die. * FIXME: Decide under what circumstances we should * acutally kill the application. */ xcb_generic_error_t *err = (xcb_generic_error_t *)evt; fprintf(stderr, "Error received in event loop.\n" "Error code: %i\n", err->error_code); if ((err->error_code >= XCB_VALUE) && (err->error_code <= XCB_FONT)) { xcb_value_error_t *val_err = (xcb_value_error_t *)evt; fprintf(stderr, "Bad value: %i\n" "Major opcode: %i\n" "Minor opcode: %i\n", val_err->bad_value, val_err->major_opcode, val_err->minor_opcode); } break; } case XCB_EXPOSE: { xcb_expose_event_t *exevnt = (xcb_expose_event_t *)evt; printf( "Window %u exposed. Region to be redrawn at location (%d, %d), ", exevnt->window, exevnt->x, exevnt->y); printf("with dimensions (%d, %d).\n", exevnt->width, exevnt->height); return_evt.event_type = XCWM_EVENT_WINDOW_EXPOSE; callback_ptr(&return_evt); break; } case XCB_CREATE_NOTIFY: { /* We don't actually allow our client to create its * window here, wait until the XCB_MAP_REQUEST */ break; } case XCB_DESTROY_NOTIFY: { // Window destroyed in root window xcb_destroy_notify_event_t *notify = (xcb_destroy_notify_event_t *)evt; xcwm_window_t *window = _xcwm_window_remove(event_conn, notify->window); if (!window) { /* Not a window in the list, don't try and destroy */ break; } return_evt.event_type = XCWM_EVENT_WINDOW_DESTROY; return_evt.window = window; callback_ptr(&return_evt); // Release memory for the window _xcwm_window_release(window); break; } case XCB_MAP_NOTIFY: { xcb_map_notify_event_t *notify = (xcb_map_notify_event_t *)evt; /* notify->event holds parent of the window */ xcwm_window_t *window = _xcwm_get_window_node_by_window_id(notify->window); if (!window) { /* No MAP_REQUEST for override-redirect windows, so need to create the xcwm_window_t for it now */ /* printf("MAP_NOTIFY without MAP_REQUEST\n"); */ window = _xcwm_window_create(context, notify->window, notify->event); if (window) { _xcwm_window_composite_pixmap_update(window); return_evt.window = window; return_evt.event_type = XCWM_EVENT_WINDOW_CREATE; callback_ptr(&return_evt); } } else { _xcwm_window_composite_pixmap_update(window); } break; } case XCB_MAP_REQUEST: { xcb_map_request_event_t *request = (xcb_map_request_event_t *)evt; /* Map the window */ xcb_map_window(context->conn, request->window); xcb_flush(context->conn); return_evt.window = _xcwm_window_create(context, request->window, request->parent); if (!return_evt.window) { break; } return_evt.event_type = XCWM_EVENT_WINDOW_CREATE; callback_ptr(&return_evt); break; } case XCB_UNMAP_NOTIFY: { xcb_unmap_notify_event_t *notify = (xcb_unmap_notify_event_t *)evt; xcwm_window_t *window = _xcwm_window_remove(event_conn, notify->window); if (!window) { /* Not a window in the list, don't try and destroy */ break; } return_evt.event_type = XCWM_EVENT_WINDOW_DESTROY; return_evt.window = window; callback_ptr(&return_evt); _xcwm_window_composite_pixmap_release(window); // Release memory for the window _xcwm_window_release(window); break; } case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *request = (xcb_configure_notify_event_t *)evt; printf("CONFIGURE_NOTIFY: XID 0x%08x %dx%d @ %d,%d\n", request->window, request->width, request->height, request->x, request->y); xcwm_window_t *window = _xcwm_get_window_node_by_window_id(request->window); if (window) _xcwm_window_composite_pixmap_update(window); break; } case XCB_CONFIGURE_REQUEST: { xcb_configure_request_event_t *request = (xcb_configure_request_event_t *)evt; printf("CONFIGURE_REQUEST: XID 0x%08x %dx%d @ %d,%d mask 0x%04x\n", request->window, request->width, request->height, request->x, request->y, request->value_mask); /* relying on the server's idea of the current values of values not in value_mask is a bad idea, we might have a configure request of our own on this window in flight */ if (request->value_mask & (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT)) _xcwm_resize_window(event_conn, request->window, request->x, request->y, request->width, request->height); /* Ignore requests to change stacking ? */ break; } case XCB_PROPERTY_NOTIFY: { xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)evt; xcwm_window_t *window = _xcwm_get_window_node_by_window_id(notify->window); if (!window) { break; } /* If this is WM_PROTOCOLS, do not send event, just * handle internally */ if (notify->atom == window->context->atoms.ewmh_conn.WM_PROTOCOLS) { _xcwm_atoms_set_wm_delete(window); break; } xcwm_event_type_t event; if (_xcwm_atom_change_to_event(notify->atom, window, &event)) { /* Send the appropriate event */ return_evt.event_type = event; return_evt.window = window; callback_ptr(&return_evt); } else { printf("PROPERTY_NOTIFY for ignored property atom %d\n", notify->atom); /* We need a mechanism to forward properties we don't know about to WM, otherwise everything needs to be in libXcwm ...? */ } break; } case XCB_MAPPING_NOTIFY: break; default: { printf("UNKNOWN EVENT: %i\n", (evt->response_type & ~0x80)); break; } } } /* Free the event */ free(evt); } return NULL; }