#!/usr/bin/env python3 from Xlib import display # from pprint import pprint as print import gi, cairo gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk, GdkPixbuf from utils import blur_image # 获取默认显示器 dp = Gdk.Display.get_default() root = display.Display().screen().root # 计算所有显示器的总大小 total_width = 0 total_height = 0 for i in range(dp.get_n_monitors()): monitor = dp.get_monitor(i) geometry = monitor.get_geometry() total_width += geometry.width total_height = max(total_height, geometry.height) def on_draw(widget, cr): cr.set_source_rgba(0, 0, 0, 0.3) # 设置颜色和透明度 cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() cr.set_operator(cairo.OPERATOR_OVER) def on_mouse_move(widget, event): print(event.x_root, event.y_root) # pointer = root.query_pointer() # print("Mouse at (%d, %d)" % (pointer.root_x, pointer.root_y)) # win_at_pointer = pointer.child # print(win_at_pointer.get_wm_class()) # print(dir(Gtk.WindowType)) # 创建遮罩窗口 class App(Gtk.Window): saved = False def __init__(self): Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP) self.set_name('Xshot') self.set_default_size(total_width, total_height) self.set_type_hint(Gdk.WindowTypeHint.DESKTOP) # 设置透明背景 screen = self.get_screen() visual = screen.get_rgba_visual() if visual and screen.is_composited(): self.set_visual(visual) self.set_app_paintable(True) self.set_focus() # self.set_events(Gdk.EventMask.POINTER_MOTION_MASK) # window.connect("button-press-event", on_mouse_move) # window.connect("button-release-event", on_mouse_move) # window.connect("motion-notify-event", on_mouse_move) # window.connect("motion-notify-event", on_mouse_move) layout = Gtk.Fixed() # self.add(layout) # layout = Gtk.Fixed() self.drawing_area = Gtk.DrawingArea() self.drawing_area.set_size_request(total_width, total_height) self.drawing_area.add_events( Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK) self.drawing_area.connect("draw", self.on_draw) self.drawing_area.connect("button-press-event", self.on_button_press) self.drawing_area.connect("button-release-event", self.on_button_release) self.drawing_area.connect("motion-notify-event", self.on_motion_notify) layout.add(self.drawing_area) btn = Gtk.Button(label = 'hello world') btn.set_size_request(200, 60) layout.put(btn, 200, 100) self.layout = layout self.add(layout) # Initialize rectangle and control point size self.start_x = None self.start_y = None self.current_x = None self.current_y = None self.dragging = False self.resize_dragging = False self.connect("draw", self.on_before_start) self.connect("delete-event", Gtk.main_quit) self.connect("key-press-event", self.on_key_down) def on_before_start(self, win, cr): if not self.saved: # print('又进来了') window = Gdk.get_default_root_window() width, height = window.get_width(), window.get_height() self.entire_desktop = Gdk.pixbuf_get_from_window(window, 0, 0, width, height) # self.entire_desktop.savev("entire_desktop.png", "png", [], []) self.saved = True cr.set_source_rgba(0, 0, 0, 0.3) # 设置颜色和透明度 cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() cr.set_operator(cairo.OPERATOR_OVER) def on_draw(self, widget, cr): if self.start_x is not None and self.start_y is not None: width = self.current_x - self.start_x height = self.current_y - self.start_y # print(abs(width), abs(height)) # 白色 # cr.set_source_rgb(1, 1, 1) cr.set_source_rgb(208/255, 234/255, 1) cr.set_line_width(2) cr.set_dash([6.0, 4.0]) cr.rectangle(self.start_x, self.start_y, width, height) cr.stroke() center = (self.start_x + width / 2, self.start_y + height / 2) # draw resizing dots for x in [self.start_x, center[0], self.current_x]: for y in [self.start_y, center[1], self.current_y]: # 中心的圆点不画 if x == center[0] and y == center[1]: continue cr.arc(x, y, 5, 0, 2 * 3.14) cr.fill() def on_button_press(self, widget, event): if event.button == 1: # left mouse button self.start_x = event.x self.start_y = event.y self.current_x = event.x self.current_y = event.y self.dragging = True def on_button_release(self, widget, event): if event.button == 1: # left mouse button self.dragging = False self.screenshot() self.queue_draw() def on_motion_notify(self, widget, event): if self.dragging: self.current_x = event.x self.current_y = event.y self.queue_draw() def screenshot(self): x = self.start_x y = self.start_y w = self.current_x - x h = self.current_y - y pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, abs(w), abs(h)) self.entire_desktop.copy_area(x, y, w, h, pixbuf, 0, 0) # pixbuf = blur_image(pixbuf) # pixbuf.savev("screenshot.png", "png", [], []) img = Gtk.Image() img.set_from_pixbuf(pixbuf) self.layout.put(img, x + 1, y + 1) self.layout.show_all() def on_key_down(self, win, ev): if ev.keyval == Gdk.KEY_Escape: Gtk.main_quit() def run(self): try: self.show_all() Gtk.main() except: pass App().run()