Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Game]: Geforce Now Streaming Service #691

Open
3 tasks done
thelege2nd opened this issue Oct 8, 2024 · 0 comments
Open
3 tasks done

[Game]: Geforce Now Streaming Service #691

thelege2nd opened this issue Oct 8, 2024 · 0 comments
Labels

Comments

@thelege2nd
Copy link

Requirements

  • This issue doesn't already exists
  • This bug is only related to a single game
  • Filled out the title with template

Summary

I'm having an issue with the GeForce Now streaming service. It always forces games to be played in full window, and I'm unable to run them in borderless mode. I've created a code that allows me to freely resize any process window, including GeForce Now, which normally enforces full window. However, after resizing, the resolution automatically reverts back to full window as soon as I click on the window, no matter what I do. This works fine for any game or process running, but inside Geforce now, it doesn't! They have some sort of protective mechanism. Any ideas how to tackle this? Does this tool use Lower-Level Hooks? You can freely download GeForce now and test it btw.
`import ctypes
import psutil
import tkinter as tk
from tkinter import ttk, messagebox
import win32api
import win32con
import win32gui
import win32process
import threading
import time

def get_processes_with_windows():
windows = []

def enum_window_callback(hwnd, extra):
    if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd):
        _, pid = win32process.GetWindowThreadProcessId(hwnd)
        try:
            process_name = psutil.Process(pid).name()
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            return
        window_title = win32gui.GetWindowText(hwnd)
        windows.append({'hwnd': hwnd, 'pid': pid, 'process_name': process_name, 'window_title': window_title})

win32gui.EnumWindows(enum_window_callback, None)

# Group windows by process
processes = {}
for win in windows:
    pid = win['pid']
    if pid not in processes:
        processes[pid] = {'pid': pid, 'process_name': win['process_name'], 'hwnds': [], 'window_titles': []}
    processes[pid]['hwnds'].append(win['hwnd'])
    processes[pid]['window_titles'].append(win['window_title'])

return list(processes.values())

def force_resizable_window(hwnd):
try:
# Get current window style
style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
ex_style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)

    # Modify the window style to make it resizable and windowed
    style = (style & ~win32con.WS_POPUP) | win32con.WS_OVERLAPPEDWINDOW
    ex_style = ex_style | win32con.WS_EX_APPWINDOW

    win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, style)
    win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style)

    # Apply the changes and redraw the window
    win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, 100, 100, 1024, 768,
                          win32con.SWP_FRAMECHANGED | win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE | win32con.SWP_NOMOVE)
except Exception as e:
    error_code = ctypes.GetLastError()
    error_message = ctypes.FormatError(error_code)
    messagebox.showerror("Error", f"Failed to modify window style: {error_message}")

def block_auto_resize(hwnd):
# Block any internal programming from automatically resizing the window
while True:
try:
# Get current window style
style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
if not (style & win32con.WS_OVERLAPPEDWINDOW):
# If the window style has reverted, force it back to resizable
force_resizable_window(hwnd)
time.sleep(0.5)
except Exception:
break

def select_process():
selected_item = tree.focus()
if selected_item:
item = tree.item(selected_item)
values = item['values']
pid = int(values[0])
hwnds = None
# Find the process in the list
for proc in processes:
if proc['pid'] == pid:
hwnds = proc['hwnds']
break
if hwnds:
for hwnd in hwnds:
force_resizable_window(hwnd)
# Start a thread to block any internal resizing attempts
threading.Thread(target=block_auto_resize, args=(hwnd,), daemon=True).start()
messagebox.showinfo("Success", "Process windows have been made resizable in windowed mode.")
else:
messagebox.showerror("Error", "Failed to find window handles for the selected process.")

def main():
global tree, processes
root = tk.Tk()
root.title("Process Window Resizer")

columns = ('pid', 'Process Name', 'Window Titles')
tree = ttk.Treeview(root, columns=columns, show='headings')
tree.heading('pid', text='PID')
tree.heading('Process Name', text='Process Name')
tree.heading('Window Titles', text='Window Titles')

processes = get_processes_with_windows()
for proc in processes:
    window_titles = "; ".join(proc['window_titles'])
    tree.insert('', tk.END, values=(proc['pid'], proc['process_name'], window_titles))

tree.pack(fill=tk.BOTH, expand=True)

button_frame = tk.Frame(root)
button_frame.pack(pady=10)

select_button = tk.Button(button_frame, text="Force Resizable Window Mode", command=select_process)
select_button.pack(side=tk.LEFT, padx=5)

root.mainloop()

if name == 'main':
main()`

Steps to reproduce

Technical details

No response

version

Geforce Now Desktop Client

@thelege2nd thelege2nd added the bug label Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant