コード例 #1
0
ファイル: hint_window.py プロジェクト: ellet/PyleWM
    def draw(self, overlay):
        if self.closed:
            return
        for item in self.item_list:
            if not item.hint.startswith(self.selection_text):
                continue

            rect = self.abs_to_overlay(item.rect)

            if item.is_hidden:
                overlay.draw_box(rect, self.bg_color)
                overlay.draw_border(rect, self.border_color, self.border_width)

                overlay.draw_text(
                    item.hint, self.hint_color,
                    Rect((rect.left + 5, rect.top, rect.left + 60,
                          rect.bottom)), (0.5, 0.5))
                overlay.draw_text(item.title,
                                  self.title_color,
                                  Rect((rect.left + 65, rect.top,
                                        rect.right - 5, rect.bottom)),
                                  (0.0, 0.5),
                                  font=overlay.font_small)
            else:
                box_rect = Rect.centered_around(rect.center, self.box_size)
                overlay.draw_box(box_rect, self.bg_color)
                if item.window.floating:
                    overlay.draw_border(box_rect, self.floating_border, 3)
                overlay.draw_text(item.hint, self.hint_color, box_rect,
                                  (0.5, 0.5))
コード例 #2
0
    def __init__(self, hwnd):
        self.handle = hwnd
        self.last_window_pos = win32gui.GetWindowRect(self.handle)
        self.last_received_pos = self.last_window_pos
        self.rect = Rect(self.last_window_pos)
        self.floating_rect = self.rect.copy()
        self.last_set_rect = self.rect.copy()
        self.window_class = win32gui.GetClassName(hwnd)
        self.window_title = win32gui.GetWindowText(hwnd)
        self.space = None
        self.closed = False
        self.focused = False
        self.hidden = False
        self.becoming_visible = False
        self.floating = False
        self.can_tile = True
        self.take_new_rect = False
        self.force_closed = False
        self.always_top = False
        self.force_always_top = False
        self.force_borders = None
        self.minimized = False
        self.is_dropdown = False

        parent_handle = win32api.GetWindowLong(self.handle, win32con.GWL_HWNDPARENT)
        self.is_child_window = win32gui.IsWindow(parent_handle)

        self.dragging = False
        self.drag_ticks_with_movement = 0
        self.drag_ticks_since_start = 0
        self.drag_ticks_since_last_movement = 0

        self.drop_space = None
        self.drop_slot = None
        self.drop_ticks_inside_slot = 0
コード例 #3
0
    def draw(self, overlay):
        if self.closed:
            return
        box_left = (self.overlay_rect.width - self.box_width) / 2
        box = Rect((box_left, 0, box_left + self.box_width,
                    self.displayed_count * self.row_height + 10 + 40))

        start_index = max(0, self.selected_index - self.context_pre)
        end_index = min(start_index + self.displayed_count, len(self.options))

        overlay.draw_box(box, self.bg_color)

        for position_index, option_index in enumerate(
                range(start_index, end_index)):
            if option_index == self.selected_index:
                overlay.draw_box(
                    Rect((box.left, box.top + self.row_height * position_index,
                          box.right, box.top + self.row_height *
                          (position_index + 1) + 5)), self.bg_selected_color)

            overlay.draw_text(
                self.options[option_index].name,
                self.text_color,
                Rect.from_pos_size(
                    (box.left + 5,
                     box.top + 5 + self.row_height * position_index),
                    (box.width - 10, self.row_height)),
                (0.0, 0.5),
            )

        if self.filter_text:
            overlay.draw_text(
                self.filter_text, self.filter_color,
                Rect.from_pos_size((box.left, box.bottom - 40),
                                   (box.width - 5, 35)), (1.0, 1.0))
コード例 #4
0
ファイル: overlay_mode.py プロジェクト: ellet/PyleWM
 def abs_to_overlay(self, rect):
     return Rect((
         rect.left - self.overlay_rect.left,
         rect.top - self.overlay_rect.top,
         rect.right - self.overlay_rect.left,
         rect.bottom - self.overlay_rect.top,
     ))
コード例 #5
0
    def start_region_mode(self):
        self.region_mode = True
        self.regions = []

        y = 10
        while y < self.cover_area.height - 10:
            x = 10
            while x < self.cover_area.width - 10:
                # If the region is all one color in the image, we consider it boring
                # and we don't add a hint to it!
                rect = Rect(
                    (x, y,
                     min(x + self.region_width, self.cover_area.width - 10),
                     min(y + self.region_height, self.cover_area.height - 10)))
                x += self.region_width

                if self.is_boring(rect):
                    continue

                region = HintRegion()
                region.rect = rect
                self.regions.append(region)
            y += self.region_height

        pylewm.modes.hint_helpers.create_hints(self.regions, self.hintkeys)
コード例 #6
0
def toggle_dropdown():
    global DROPDOWN_WINDOW
    window = DROPDOWN_WINDOW

    if not window:
        return

    monitor = pylewm.focus.get_focused_monitor()

    width = monitor.rect.width / 2
    height = monitor.rect.height / 3

    dropdown_rect = Rect.from_pos_size(
        (monitor.rect.left +
         (monitor.rect.width - width) / 2, monitor.rect.top),
        (width, height),
    )

    if window.hidden:
        print("Show dropdown window at " + str(dropdown_rect))
        window.show_with_rect(dropdown_rect)
        pylewm.focus.set_focus_no_mouse(window)
    else:
        print("Hide dropdown window")
        window.hide()
コード例 #7
0
ファイル: keynav.py プロジェクト: ellet/PyleWM
    def shift(self, x, y):
        w, h = self.rect.width, self.rect.height
        left = min(max(0, self.rect.left + x), self.cover_area.width - w)
        top = min(max(0, self.rect.top + y), self.cover_area.height - h)

        self.rect = Rect((left, top, left+w, top+h))
        self.update_rect()
コード例 #8
0
ファイル: keynav.py プロジェクト: ellet/PyleWM
 def split_right(self):
     self.rect = Rect((
         self.rect.left + self.rect.width / 2,
         self.rect.top,
         self.rect.right,
         self.rect.bottom,
     ))
     self.update_rect()
コード例 #9
0
ファイル: keynav.py プロジェクト: ellet/PyleWM
 def split_down(self):
     self.rect = Rect((
         self.rect.left,
         self.rect.top + self.rect.height / 2,
         self.rect.right,
         self.rect.bottom,
     ))
     self.update_rect()
コード例 #10
0
ファイル: keynav.py プロジェクト: ellet/PyleWM
 def split_up(self):
     self.rect = Rect((
         self.rect.left,
         self.rect.top,
         self.rect.right,
         self.rect.top + self.rect.height / 2,
     ))
     self.update_rect()
コード例 #11
0
ファイル: hint_window.py プロジェクト: ellet/PyleWM
    def __init__(self, hintkeys, hotkeys):
        super(HintWindowMode, self).__init__(hotkeys)
        self.hintkeys = hintkeys
        self.item_list = []
        self.overlay_global()

        self.bg_color = (0, 0, 0)
        self.hint_color = (255, 255, 0)
        self.border_color = (0, 128, 255)
        self.title_color = (128, 128, 128)
        self.floating_border = (255, 0, 255)
        self.border_width = 1
        self.box_size = (200, 50)

        self.selection_text = ""
        self.max_hidden_row = 10
        self.closed = False
        self.dirty = True

        hidden_windows = {}
        for hwnd, window in pylewm.windows.Windows.items():
            if win32gui.IsWindow(hwnd):
                if window.is_dropdown:
                    continue
                if window.minimized:
                    continue
                if window.space and not window.space.visible:
                    if window.space.monitor not in hidden_windows:
                        hidden_windows[window.space.monitor] = []
                    hidden_windows[window.space.monitor].append(window)
                    continue

                item = WindowItem()
                item.window = window
                item.rect = window.rect
                item.is_hidden = False
                self.item_list.append(item)

        for monitor, window_list in hidden_windows.items():
            show_count = len(window_list)
            item_width = monitor.rect.width / min(self.max_hidden_row,
                                                  show_count)
            for i in range(0, show_count):
                window = window_list[i]

                item = WindowItem()
                item.window = window
                item.title = win32gui.GetWindowText(window.handle)
                item.rect = Rect.from_pos_size(
                    (monitor.rect.left +
                     (i % self.max_hidden_row) * item_width,
                     monitor.rect.bottom - 30 *
                     (int(i / self.max_hidden_row) + 1)), (item_width, 30))
                item.is_hidden = True
                self.item_list.append(item)

        pylewm.modes.hint_helpers.create_hints(self.item_list, self.hintkeys)
コード例 #12
0
    def draw(self, overlay):
        if self.closed:
            return

        if self.region_mode:
            for i, region in enumerate(self.regions):
                if not region.hint.startswith(self.selection_text):
                    continue

                overlay.draw_text(region.hint,
                                  self.hint_color,
                                  region.rect.shifted((0, -2)), (0.5, 0.5),
                                  font=overlay.font_small,
                                  background_box=(0, 0, 0))
        else:
            overlay.draw_box(
                Rect.centered_around(self.selected_region.rect.center,
                                     (10, 10)), self.center_color)
            #overlay.draw_border(self.selected_region.rect, self.center_color, 1)

            for i, point in enumerate(self.points):
                if not point.hint.startswith(self.selection_text):
                    continue
                if point.hidden:
                    continue
                overlay.draw_box(
                    Rect.from_pos_size(
                        (point.position[0] - 2,
                         point.position[1] - max(point.offset, 0)),
                        (4, abs(point.offset))), self.line_color)

                overlay.draw_text(
                    point.hint,
                    self.hint_color,
                    Rect.centered_around(
                        (point.position[0], point.position[1] - point.offset),
                        (50, 50)), (0.5, 0.5),
                    font=overlay.font_small,
                    background_box=(0, 0, 0))

                overlay.draw_box(Rect.centered_around(point.position, (6, 6)),
                                 self.hint_color)
コード例 #13
0
ファイル: keynav.py プロジェクト: ellet/PyleWM
 def draw(self, overlay):
     overlay.draw_border(Rect((
         self.rect.left, self.rect.top,
         self.rect.left + self.rect.width / 2, self.rect.top + self.rect.height / 2
     )), self.line_color, self.line_width)
     overlay.draw_border(Rect((
         self.rect.left + self.rect.width / 2, self.rect.top,
         self.rect.right, self.rect.top + self.rect.height / 2
     )), self.line_color, self.line_width)
     overlay.draw_border(Rect((
         self.rect.left, self.rect.top + self.rect.height / 2,
         self.rect.left + self.rect.width / 2, self.rect.bottom
     )), self.line_color, self.line_width)
     overlay.draw_border(Rect((
         self.rect.left + self.rect.width / 2, self.rect.top + self.rect.height / 2,
         self.rect.right, self.rect.bottom
     )), self.line_color, self.line_width)
     overlay.draw_box(Rect((
         self.rect.left + self.rect.width / 2 - self.target_width, self.rect.top + self.rect.height / 2 - self.target_width,
         self.rect.left + self.rect.width / 2 + self.target_width, self.rect.top + self.rect.height / 2 + self.target_width,
     )), self.target_color)
コード例 #14
0
    def __init__(self, info):
        self.info = info
        self.rect = Rect(info['Work'])
        self.primary = info["Flags"] & 1

        self.spaces = [Space(self, self.rect), Space(self, self.rect)]
        self.last_used_space = None

        self.temp_spaces = []
        self.last_used_temp_space = None

        self.visible_space = self.spaces[0]
        self.visible_space.visible = True
コード例 #15
0
ファイル: keynav.py プロジェクト: ellet/PyleWM
    def __init__(self, hotkeys):
        self.window = pylewm.focus.FocusWindow
        self.cover_area = self.window.rect

        self.rect = Rect((0, 0, self.cover_area.width, self.cover_area.height))
        self.overlay_window(self.window)

        self.line_color = (255, 0, 0)
        self.line_width = 3

        self.target_color = (0, 255, 255)
        self.target_width = 6

        self.rect_history = []
        self.update_rect()

        super(KeyNavMode, self).__init__(hotkeys)
コード例 #16
0
ファイル: layout.py プロジェクト: ellet/PyleWM
 def __init__(self):
     self.windows = []
     self.rect = Rect()
     self.pending_drop_slot = None
     self.focus = None
     self.focus_mru = []
コード例 #17
0
class Window:
    def __init__(self, hwnd):
        self.handle = hwnd
        self.last_window_pos = win32gui.GetWindowRect(self.handle)
        self.last_received_pos = self.last_window_pos
        self.rect = Rect(self.last_window_pos)
        self.floating_rect = self.rect.copy()
        self.last_set_rect = self.rect.copy()
        self.window_class = win32gui.GetClassName(hwnd)
        self.window_title = win32gui.GetWindowText(hwnd)
        self.space = None
        self.closed = False
        self.focused = False
        self.hidden = False
        self.becoming_visible = False
        self.floating = False
        self.can_tile = True
        self.take_new_rect = False
        self.force_closed = False
        self.always_top = False
        self.force_always_top = False
        self.force_borders = None
        self.minimized = False
        self.is_dropdown = False

        parent_handle = win32api.GetWindowLong(self.handle, win32con.GWL_HWNDPARENT)
        self.is_child_window = win32gui.IsWindow(parent_handle)

        self.dragging = False
        self.drag_ticks_with_movement = 0
        self.drag_ticks_since_start = 0
        self.drag_ticks_since_last_movement = 0

        self.drop_space = None
        self.drop_slot = None
        self.drop_ticks_inside_slot = 0

    def reset(self):
        print("Close due to reset: "+self.window_title)
        self.closed = True
        if self.hidden:
            self.hidden = False
            self.becoming_visible = True
            ctypes.windll.user32.ShowWindowAsync(self.handle, win32con.SW_SHOWNOACTIVATE)
        if self.always_top:
            self.set_always_top(False)

    def show(self):
        def show_cmd():
            if not self.hidden:
                return
            self.hidden = False
            self.becoming_visible = True
            ctypes.windll.user32.ShowWindowAsync(self.handle, win32con.SW_SHOWNOACTIVATE)
            self.bring_to_front()

            #if win32gui.IsIconic(self.handle):
                #win32gui.ShowWindow(self.handle, win32con.SW_RESTORE)
            #self.last_window_pos = self.get_actual_rect()
        self.command_queue.queue_command(show_cmd)

    def SetWindowPos(self, hwnd, insert_hwnd, pos_x, pos_y, pos_cx, pos_cy, flags):
        result = ctypes.windll.user32.SetWindowPos(
            hwnd, insert_hwnd,
            pos_x, pos_y,
            pos_cx, pos_cy,
            flags
        )
        return (result != 0)

    def show_with_rect(self, new_rect):
        self.rect = new_rect
        def show_with_rect_cmd():
            if not self.hidden:
                return
            self.hidden = False
            self.becoming_visible = True

            try_position = [
                self.rect.left,
                self.rect.top,
                self.rect.width,
                self.rect.height,
            ]
            self.SetWindowPos(self.handle, win32con.HWND_TOPMOST,
                try_position[0], try_position[1],
                try_position[2], try_position[3],
                win32con.SWP_SHOWWINDOW)

            ctypes.windll.user32.ShowWindowAsync(self.handle, win32con.SW_SHOW)

        self.command_queue.queue_command(show_with_rect_cmd)

    def hide(self):
        def hide_cmd():
            if self.hidden:
                return
            self.hidden = True
            self.becoming_visible = False
            time.sleep(0.05)
            ctypes.windll.user32.ShowWindowAsync(self.handle, win32con.SW_HIDE)

            #if not win32gui.IsIconic(self.handle):
                #win32gui.ShowWindow(self.handle, win32con.SW_FORCEMINIMIZE)
        self.command_queue.queue_command(hide_cmd)

    def minimize(self):
        def minimize_cmd():
            minimize_window_handle(self.handle)

        self.minimized = True
        self.floating = True
        self.dragging = False
        self.command_queue.queue_command(minimize_cmd)

    def remove_titlebar(self):
        def remove_titlebar_cmd():
            style = win32api.GetWindowLong(self.handle, win32con.GWL_STYLE)
            if style & win32con.WS_CAPTION:
                style = style & ~win32con.WS_CAPTION
                win32api.SetWindowLong(self.handle, win32con.GWL_STYLE, style)
        self.command_queue.queue_command(remove_titlebar_cmd)

    def manage(self):
        self.command_queue = pylewm.commands.CommandQueue()
        def manage_window_cmd():
            if self.is_maximized():
                self.remove_maximize()
                self.last_window_pos = win32gui.GetWindowRect(self.handle)
            if self.floating:
                self.set_always_top(True)
            elif self.force_always_top:
                self.set_always_top(True)
            else:
                self.bring_to_front()
        self.command_queue.queue_command(manage_window_cmd)

    def trigger_update(self):
        self.command_queue.queue_command(self.update)

    def stop_managing(self):
        self.command_queue.stop()
        self.remove_drop_space()

    def is_cloaked(self):
        return is_window_handle_cloaked(self.handle)

    def is_maximized(self):
        try:
            style = win32api.GetWindowLong(self.handle, win32con.GWL_STYLE)
            return style & win32con.WS_MAXIMIZE
        except:
            return False

    def is_minimized(self):
        try:
            style = win32api.GetWindowLong(self.handle, win32con.GWL_STYLE)
            return style & win32con.WS_MINIMIZE
        except:
            return False

    def is_window_hidden(self):
        try:
            return not win32gui.IsWindowVisible(self.handle)
        except:
            return False

    def remove_maximize(self):
        win32gui.ShowWindow(self.handle, win32con.SW_SHOWNOACTIVATE)

    def get_actual_rect(self):
        try:
            return win32gui.GetWindowRect(self.handle)
        except:
            return self.rect.coordinates

    def can_move(self):
        if ctypes.windll.user32.IsHungAppWindow(self.handle):
            return False
        return True

    def update_drag(self):
        new_rect = self.get_actual_rect()
        if self.take_new_rect:
            self.last_window_pos = new_rect
            self.take_new_rect = False
            self.dragging = False
            self.remove_drop_space()

        # Some rudimentary tracking for when windows are being dragged
        if new_rect != self.last_window_pos:
            if is_left_mouse_held():
                if self.dragging:
                    self.drag_ticks_since_last_movement = 0
                    self.drag_ticks_since_start += 1
                    self.drag_ticks_with_movement += 1
                else:
                    self.dragging = True
                    self.drag_ticks_since_last_movement = 0
                    self.drag_ticks_since_start = 1
                    self.drag_ticks_with_movement = 1
        else:
            if self.dragging:
                self.drag_ticks_since_start += 1
                self.drag_ticks_since_last_movement += 1

                if not is_left_mouse_held():
                    self.dragging = False

        self.last_window_pos = new_rect
        if self.floating:
            self.rect.coordinates = new_rect
            self.floating_rect.coordinates = new_rect

    def update_float_drop(self):
        if not self.can_tile:
            return
        if self.dragging and self.drag_ticks_with_movement > 5:
            hover_space = pylewm.focus.get_cursor_space()
            hover_slot = None
            if hover_space:
                hover_slot, force_drop = hover_space.get_drop_slot(pylewm.focus.get_cursor_position(), self.rect)

                # Only allow forced drops when drag&dropping
                if not force_drop:
                    hover_slot = None
            
            if hover_slot is not None:
                self.set_drop_space(hover_space, hover_slot)
            else:
                self.remove_drop_space()
        elif not self.dragging and self.drop_space and self.drop_slot is not None and self.drop_ticks_inside_slot >= 3:
            self.floating = False
            self.take_new_rect = True
            self.drop_space.add_window(self, at_slot=self.drop_slot)
            self.remove_drop_space()
        else:
            self.remove_drop_space()

    def set_drop_space(self, new_space, new_slot):
        if self.drop_space == new_space and self.drop_slot == new_slot:
            if self.drop_ticks_inside_slot == 2:
                self.drop_space.set_pending_drop_slot(self.drop_slot)
            self.drop_ticks_inside_slot += 1
        else:
            if self.drop_space:
                self.drop_space.set_pending_drop_slot(None)
            self.drop_space = new_space
            self.drop_slot = new_slot
            self.drop_ticks_inside_slot = 0

    def remove_drop_space(self):
        if self.drop_space:
            self.drop_space.set_pending_drop_slot(None)
        self.drop_ticks_inside_slot = 0
        self.drop_space = None
        self.drop_slot = None

    def update(self):
        if self.hidden:
            return
        if self.closed:
            return
        if not win32gui.IsWindow(self.handle):
            print("Close due to not handle: "+self.window_title)
            self.closed = True
            return
        if self.is_cloaked():
            print("Close due to cloaked: "+self.window_title)
            self.closed = True
            return
        if self.is_minimized() or (self.is_window_hidden() and not self.becoming_visible):
            # Manually minimized windows are considered closed
            if not self.minimized:
                print("Close due to minimize: "+self.window_title)
                self.minimized = True
                self.floating = True
                self.dragging = False
                return
        else:
            if not self.is_window_hidden():
                self.becoming_visible = False
            if self.minimized:
                print("Reopen from minimize: "+self.window_title)
                self.minimized = False
                if not self.can_tile:
                    return
                hover_space = pylewm.focus.get_cursor_space()
                if hover_space:
                    hover_slot, force_drop = hover_space.get_drop_slot(self.rect.center, self.rect)
                    if hover_slot and not self.take_new_rect:
                        hover_space.add_window(self, at_slot=hover_slot)
                    else:
                        hover_space.add_window(self)
                    self.floating = False
                else:
                    self.floating = True
                self.take_new_rect = True
        if self.minimized:
            return
        if self.floating:
            self.update_drag()
            if self.dragging or self.drop_space:
                self.update_float_drop()
            return

        self.update_drag()

        # Move back to the bottom if we managed to get always on top
        if self.always_top and not self.force_always_top:
            self.set_always_top(False)

        # If the window has been moved outside of PyleWM we 'unsnap' it from the layout
        #  This is the same operation as 'closing' it since we are no longer managing it
        if self.is_maximized() or (self.dragging and (self.drag_ticks_with_movement > 2 or is_left_mouse_held())):
            self.set_always_top(True)
            self.floating = True
            self.dragging = False
            return

        # Move the window to the wanted rect if it has changed
        if not self.dragging and self.space and (
                not Rect.equal_coordinates(self.last_window_pos, self.last_received_pos)
                or not self.rect.equals(self.last_set_rect)):

            new_rect = self.rect.copy()
            try_position = [
                self.rect.left,
                self.rect.top,
                self.rect.width,
                self.rect.height,
            ]
            self.adjust_position_for_window(try_position)

            set_position_allowed = True
            needed_tries = 0
            for tries in range(0, 10):
                set_position_allowed = self.SetWindowPos(self.handle, win32con.HWND_BOTTOM,
                    try_position[0], try_position[1],
                    try_position[2], try_position[3],
                    win32con.SWP_NOACTIVATE)
                if not set_position_allowed:
                    break

                self.last_window_pos = self.get_actual_rect()

                if (try_position[0] != self.last_window_pos[0]
                    or try_position[1] != self.last_window_pos[1]
                    or try_position[2] != (self.last_window_pos[2] - self.last_window_pos[0])
                    or try_position[3] != (self.last_window_pos[3] - self.last_window_pos[1])
                ):
                    # Keep trying!
                    continue
                else:
                    needed_tries = tries+1
                    break

            if set_position_allowed:
                self.last_set_rect.assign(new_rect)
                self.last_window_pos = self.get_actual_rect()
                self.last_received_pos = self.last_window_pos

                print(f"Received {self.last_received_pos} for {self.window_title} which wants {new_rect} after {needed_tries} tries")
            else:
                print(f"Failed to set {new_rect} on {self.window_title}")

    def adjust_position_for_window(self, position):
        if self.force_borders is not None:
            if self.force_borders == 0:
                return
            else:
                position[0] += self.force_borders
                position[1] += self.force_borders
                position[2] -= self.force_borders*2
                position[3] -= self.force_borders*2
                return

        style = win32api.GetWindowLong(self.handle, win32con.GWL_STYLE)

        if not (style & win32con.WS_SYSMENU):
            position[0] += 2
            position[2] -= 4
            position[3] -= 3
            return

        exStyle = win32api.GetWindowLong(self.handle, win32con.GWL_EXSTYLE)

        adjusted = ctypes.wintypes.RECT()
        adjusted.left = position[0]
        adjusted.top = position[1]
        adjusted.right = position[0] + position[2]
        adjusted.bottom = position[1] + position[3]

        ctypes.windll.user32.AdjustWindowRectEx(
            ctypes.pointer(adjusted),
            ctypes.c_uint(style),
            False,
            ctypes.c_uint(exStyle),
        )

        position[0] = adjusted.left + 3
        position[1] += 2
        position[2] = adjusted.right - adjusted.left - 6
        position[3] = adjusted.bottom - position[1] - 3

    def make_floating(self):
        space = self.space
        if space:
            space.remove_window(self)

        self.floating = True
        self.can_tile = False

        def float_cmd():
            # Floating windows are always on top of everything
            self.set_always_top(True)

            # Return window to the position it had before
            try_position = [
                self.floating_rect.left,
                self.floating_rect.top,
                self.floating_rect.width,
                self.floating_rect.height,
            ]

            self.SetWindowPos(self.handle, win32con.HWND_TOPMOST,
                    try_position[0], try_position[1],
                    try_position[2], try_position[3],
                    win32con.SWP_NOACTIVATE)

        self.command_queue.queue_command(float_cmd)

    def poke(self):
        def poke_cmd():
            self.SetWindowPos(self.handle, win32con.HWND_BOTTOM,
                self.rect.left+2, self.rect.top+2,
                self.rect.width-4, self.rect.height-4,
                win32con.SWP_NOACTIVATE)
            self.SetWindowPos(self.handle, win32con.HWND_BOTTOM,
                self.rect.left, self.rect.top,
                self.rect.width, self.rect.height,
                win32con.SWP_NOACTIVATE)
        self.command_queue.queue_command(poke_cmd)

    def bring_to_front(self):
        if self.force_always_top:
            return

        self.SetWindowPos(self.handle, win32con.HWND_TOP, 0, 0, 0, 0,
                win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)

    def send_to_bottom(self):
        if self.force_always_top:
            return
        self.SetWindowPos(self.handle, win32con.HWND_BOTTOM, 0, 0, 0, 0,
                win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)

    def set_always_top(self, always_top):
        self.always_top = always_top
        try:
            if always_top:
                self.SetWindowPos(self.handle, win32con.HWND_TOPMOST, 0, 0, 0, 0,
                        win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
            else:
                self.SetWindowPos(self.handle, win32con.HWND_NOTOPMOST, 0, 0, 0, 0,
                        win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
        except:
            pass
コード例 #18
0
    def update(self):
        if self.hidden:
            return
        if self.closed:
            return
        if not win32gui.IsWindow(self.handle):
            print("Close due to not handle: "+self.window_title)
            self.closed = True
            return
        if self.is_cloaked():
            print("Close due to cloaked: "+self.window_title)
            self.closed = True
            return
        if self.is_minimized() or (self.is_window_hidden() and not self.becoming_visible):
            # Manually minimized windows are considered closed
            if not self.minimized:
                print("Close due to minimize: "+self.window_title)
                self.minimized = True
                self.floating = True
                self.dragging = False
                return
        else:
            if not self.is_window_hidden():
                self.becoming_visible = False
            if self.minimized:
                print("Reopen from minimize: "+self.window_title)
                self.minimized = False
                if not self.can_tile:
                    return
                hover_space = pylewm.focus.get_cursor_space()
                if hover_space:
                    hover_slot, force_drop = hover_space.get_drop_slot(self.rect.center, self.rect)
                    if hover_slot and not self.take_new_rect:
                        hover_space.add_window(self, at_slot=hover_slot)
                    else:
                        hover_space.add_window(self)
                    self.floating = False
                else:
                    self.floating = True
                self.take_new_rect = True
        if self.minimized:
            return
        if self.floating:
            self.update_drag()
            if self.dragging or self.drop_space:
                self.update_float_drop()
            return

        self.update_drag()

        # Move back to the bottom if we managed to get always on top
        if self.always_top and not self.force_always_top:
            self.set_always_top(False)

        # If the window has been moved outside of PyleWM we 'unsnap' it from the layout
        #  This is the same operation as 'closing' it since we are no longer managing it
        if self.is_maximized() or (self.dragging and (self.drag_ticks_with_movement > 2 or is_left_mouse_held())):
            self.set_always_top(True)
            self.floating = True
            self.dragging = False
            return

        # Move the window to the wanted rect if it has changed
        if not self.dragging and self.space and (
                not Rect.equal_coordinates(self.last_window_pos, self.last_received_pos)
                or not self.rect.equals(self.last_set_rect)):

            new_rect = self.rect.copy()
            try_position = [
                self.rect.left,
                self.rect.top,
                self.rect.width,
                self.rect.height,
            ]
            self.adjust_position_for_window(try_position)

            set_position_allowed = True
            needed_tries = 0
            for tries in range(0, 10):
                set_position_allowed = self.SetWindowPos(self.handle, win32con.HWND_BOTTOM,
                    try_position[0], try_position[1],
                    try_position[2], try_position[3],
                    win32con.SWP_NOACTIVATE)
                if not set_position_allowed:
                    break

                self.last_window_pos = self.get_actual_rect()

                if (try_position[0] != self.last_window_pos[0]
                    or try_position[1] != self.last_window_pos[1]
                    or try_position[2] != (self.last_window_pos[2] - self.last_window_pos[0])
                    or try_position[3] != (self.last_window_pos[3] - self.last_window_pos[1])
                ):
                    # Keep trying!
                    continue
                else:
                    needed_tries = tries+1
                    break

            if set_position_allowed:
                self.last_set_rect.assign(new_rect)
                self.last_window_pos = self.get_actual_rect()
                self.last_received_pos = self.last_window_pos

                print(f"Received {self.last_received_pos} for {self.window_title} which wants {new_rect} after {needed_tries} tries")
            else:
                print(f"Failed to set {new_rect} on {self.window_title}")
コード例 #19
0
ファイル: overlay_mode.py プロジェクト: ellet/PyleWM
    def window_loop(self):
        pygame.init()
        pygame.fastevent.init()

        ttf_path = os.path.join(os.path.dirname(__file__), "..", "data",
                                "TerminusTTF-Bold-4.47.0.ttf")
        self.font = pygame.font.Font(ttf_path, 24)
        if not self.font:
            self.font = pygame.font.SysFont(None, 24)

        self.font_small = pygame.font.Font(ttf_path, 16)
        if not self.font:
            self.font_small = pygame.font.SysFont(None, 16)

        self.display = pygame.display.set_mode((100, 100),
                                               pygame.NOFRAME | pygame.HIDDEN)
        pygame.display.set_caption("PyleWM_Internal")

        self.hwnd = pygame.display.get_wm_info()["window"]
        win32gui.SetWindowLong(
            self.hwnd, win32con.GWL_EXSTYLE,
            win32gui.GetWindowLong(self.hwnd, win32con.GWL_EXSTYLE)
            | win32con.WS_EX_LAYERED)
        win32gui.SetLayeredWindowAttributes(self.hwnd,
                                            win32api.RGB(*self.bg_color), 0,
                                            win32con.LWA_COLORKEY)

        self.display = pygame.display.set_mode(self.overlay_area.size,
                                               pygame.NOFRAME | pygame.SHOWN)
        win32gui.SetWindowPos(self.hwnd, win32con.HWND_TOPMOST,
                              self.overlay_area.left, self.overlay_area.top,
                              self.overlay_area.width,
                              self.overlay_area.height, 0)
        self.display.fill(self.bg_color)

        self.initialized = True
        while not pylewm.commands.stopped:
            while not self.shown and not pylewm.commands.stopped:
                pygame.time.set_timer(pygame.USEREVENT, 100)
                while pygame.fastevent.wait():
                    pygame.time.set_timer(pygame.USEREVENT, 100)
                    if self.shown or pylewm.commands.stopped:
                        break

            if pylewm.commands.stopped:
                break

            win32gui.SetWindowPos(self.hwnd, win32con.HWND_TOPMOST,
                                  self.render_area.left, self.render_area.top,
                                  self.render_area.width,
                                  self.render_area.height, 0)
            win32gui.ShowWindow(self.hwnd, win32con.SW_SHOWNORMAL)

            while self.shown and not pylewm.commands.stopped:
                while pygame.fastevent.get():
                    pass
                dirty = False
                with pylewm.hotkeys.ModeLock:
                    if self.mode and self.mode in pylewm.hotkeys.ModeStack:
                        if self.mode.should_draw():
                            dirty = True
                            if self.mode.should_clear():
                                self.draw_box(
                                    Rect((0, 0, self.render_area.width,
                                          self.render_area.height)),
                                    self.bg_color)
                            self.mode.draw(self)
                if dirty:
                    pygame.display.update()

            self.display.fill(self.bg_color)
            pygame.display.update()
            win32gui.ShowWindow(self.hwnd, win32con.SW_HIDE)

        pygame.quit()
コード例 #20
0
from pylewm.rects import Rect
from pylewm.commands import PyleInit, PyleCommand
from pylewm.space import Space
from pylewm.layout import Direction

import ctypes
import math
import win32api, win32con

Monitors = []
DesktopArea = Rect()


class Monitor:
    def __init__(self, info):
        self.info = info
        self.rect = Rect(info['Work'])
        self.primary = info["Flags"] & 1

        self.spaces = [Space(self, self.rect), Space(self, self.rect)]
        self.last_used_space = None

        self.temp_spaces = []
        self.last_used_temp_space = None

        self.visible_space = self.spaces[0]
        self.visible_space.visible = True

    def switch_to_space(self, new_space):
        if new_space == self.visible_space:
            return