Potrzebuję narysować kształt bezpośrednio na ekranie (mała strzałka) w X11, służy on jako nakładka. Szukam około godziny nie bez dobrych wyników. Czy ktokolwiek mógłby mi zapewnić dobry punkt wyjścia do tego, czego potrzebuję? Technologie, z których mogę korzystać to cairo, gtk lub XLib.X11: Rysuj nakładkę/Usuń rysunki z nakładki
Wszystko, co znalazłem do tej pory, zależy od kompozycji, która nie zawsze jest dostępna, lub tworzy biały kształt za moją strzałką (prostokąt, okno).
EDYCJA: Teraz jestem w stanie narysować nakładkę X11 za pomocą kompozytów i Kairu. Robię to w ten sposób (uwaga: jest to minimalny przykład, ma niewiele do sprawdzenia błędów !!!). Zacznij od Terminalu, aby go zamknąć!
// COMPILE WITH: g++ -o overlay overlay.cc -lXfixes -lXcomposite -lX11 `pkg-config --cflags --libs cairo`
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#include <stdio.h>
#include <unistd.h>
Display *display_;
int old_x_, old_y_;
cairo_surface_t *surf_;
Window overlay_;
int screen_;
int height_;
int width_;
cairo_t *cr_;
void paint_cursor(int new_x, int new_y, bool first = false)
{
if (!first)
{
cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
cairo_rectangle(cr_, old_x_, old_y_, 20, 20);
cairo_fill(cr_);
}
old_x_ = new_x;
old_y_ = new_y;
cairo_set_operator(cr_, CAIRO_OPERATOR_SOURCE);
cairo_move_to(cr_, new_x, new_y);
cairo_line_to(cr_, new_x + 0, new_y + 16);
cairo_line_to(cr_, new_x + 4, new_y + 13);
cairo_line_to(cr_, new_x + 7, new_y + 18);
cairo_line_to(cr_, new_x + 9, new_y + 17);
cairo_line_to(cr_, new_x + 6, new_y + 12);
cairo_line_to(cr_, new_x + 11, new_y + 12);
cairo_line_to(cr_, new_x + 0, new_y + 0);
cairo_set_source_rgba(cr_, 0.0, 0.0, 0.0, 0.5);
cairo_stroke_preserve(cr_);
cairo_set_source_rgba(cr_, 0.0, 1.0, 0.0, 0.5);
cairo_fill(cr_);
}
int main()
{
display_ = ::XOpenDisplay(0);
if (!display_)
{
return -1;
}
screen_ = ::XDefaultScreen(display_);
Window root = RootWindow(display_, screen_);
::XCompositeRedirectSubwindows(display_, root, CompositeRedirectAutomatic);
::XSelectInput(display_, root, SubstructureNotifyMask);
overlay_ = ::XCompositeGetOverlayWindow(display_, root);
XserverRegion region = ::XFixesCreateRegion(display_, 0, 0);
::XFixesSetWindowShapeRegion(display_, overlay_, ShapeBounding, 0, 0, 0);
::XFixesSetWindowShapeRegion(display_, overlay_, ShapeInput, 0, 0, region);
::XFixesDestroyRegion(display_, region);
width_ = DisplayWidth(display_, screen_);
height_ = DisplayHeight(display_, screen_);
surf_ = ::cairo_xlib_surface_create(display_, overlay_, DefaultVisual(display_, screen_), width_, height_);
cr_ = ::cairo_create(surf_);
::XSelectInput(display_, overlay_, ExposureMask);
old_x_ = 0;
old_y_ = 0;
paint_cursor(0, 0, true);
XEvent ev;
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask;
for (;;)
{
XQueryPointer(display_, root, &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &mask);
paint_cursor(root_x_return, root_y_return);
printf("Paint\n");
}
return 0;
}
Pozostało pytanie: Jak usunąć stary kursor, który został narysowany? Spróbowałem XClearArea, próbowałem przemalować Kair, spróbowałem operatora Clear Cairo, itp. Nic nie działało. Czy ktoś może skierować mnie tutaj w dobrym kierunku?
Core X11 tego nie robi, będziesz potrzebować jakiegoś rozszerzenia. Możesz użyć rozszerzenia złożonego lub kształtu. Kształt jest łatwiej dostępny niż kompozyt. Możesz także użyć nakładki wizualnej, jeśli jest dostępna (wymaga obsługi OpenGL i nakładki w sprzęcie). –
Można również rysować bezpośrednio nad istniejącymi oknami, ale nie jest to zalecane. Jeśli inny program próbuje odświeżyć w tym samym czasie, wynik może nie wyglądać prawidłowo. –
Spójrz na źródło xeyes. Starożytne, ale działa. –