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))
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 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))
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, ))
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)
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()
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()
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()
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()
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()
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)
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)
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)
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 __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)
def __init__(self): self.windows = [] self.rect = Rect() self.pending_drop_slot = None self.focus = None self.focus_mru = []
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
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 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()
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