def do_give_client_focus(self): focuslog("Giving focus to %#x", self.xid) # Have to fetch the time, not just use CurrentTime, both because ICCCM # says that WM_TAKE_FOCUS must use a real time and because there are # genuine race conditions here (e.g. suppose the client does not # actually get around to requesting the focus until after we have # already changed our mind and decided to give it to someone else). now = gdk.x11_get_server_time(self.corral_window) # ICCCM 4.1.7 *claims* to describe how we are supposed to give focus # to a window, but it is completely opaque. From reading the # metacity, kwin, gtk+, and qt code, it appears that the actual rules # for giving focus are: # -- the WM_HINTS input field determines whether the WM should call # XSetInputFocus # -- independently, the WM_TAKE_FOCUS protocol determines whether # the WM should send a WM_TAKE_FOCUS ClientMessage. # If both are set, both methods MUST be used together. For example, # GTK+ apps respect WM_TAKE_FOCUS alone but I'm not sure they handle # XSetInputFocus well, while Qt apps ignore (!!!) WM_TAKE_FOCUS # (unless they have a modal window), and just expect to get focus from # the WM's XSetInputFocus. if bool(self._input_field): focuslog("... using XSetInputFocus") X11Window.XSetInputFocus(self.xid, now) if "WM_TAKE_FOCUS" in self.get_property("protocols"): focuslog("... using WM_TAKE_FOCUS") send_wm_take_focus(self.client_window, now) self.set_active()
def do_give_client_focus(self): focuslog("Giving focus to %#x", self.xid) # Have to fetch the time, not just use CurrentTime, both because ICCCM # says that WM_TAKE_FOCUS must use a real time and because there are # genuine race conditions here (e.g. suppose the client does not # actually get around to requesting the focus until after we have # already changed our mind and decided to give it to someone else). now = gtk.gdk.x11_get_server_time(self.corral_window) # ICCCM 4.1.7 *claims* to describe how we are supposed to give focus # to a window, but it is completely opaque. From reading the # metacity, kwin, gtk+, and qt code, it appears that the actual rules # for giving focus are: # -- the WM_HINTS input field determines whether the WM should call # XSetInputFocus # -- independently, the WM_TAKE_FOCUS protocol determines whether # the WM should send a WM_TAKE_FOCUS ClientMessage. # If both are set, both methods MUST be used together. For example, # GTK+ apps respect WM_TAKE_FOCUS alone but I'm not sure they handle # XSetInputFocus well, while Qt apps ignore (!!!) WM_TAKE_FOCUS # (unless they have a modal window), and just expect to get focus from # the WM's XSetInputFocus. if bool(self._input_field): focuslog("... using XSetInputFocus") X11Window.XSetInputFocus(self.xid, now) if "WM_TAKE_FOCUS" in self.get_property("protocols"): focuslog("... using WM_TAKE_FOCUS") send_wm_take_focus(self.client_window, now) self.set_active()
def _take_focus(self): focuslog("Take Focus -> world window") assert self.flags() & gtk.REALIZED # Weird hack: we are a GDK window, and the only way to properly get # input focus to a GDK window is to send it WM_TAKE_FOCUS. So this is # sending a WM_TAKE_FOCUS to our own window, which will go to the X # server and then come back to our own process, which will then issue # an XSetInputFocus on itself. now = gtk.gdk.x11_get_server_time(self.window) send_wm_take_focus(self.window, now)
def _take_focus(self): focuslog("Take Focus -> world window") assert is_realized(self) # Weird hack: we are a GDK window, and the only way to properly get # input focus to a GDK window is to send it WM_TAKE_FOCUS. So this is # sending a WM_TAKE_FOCUS to our own window, which will go to the X # server and then come back to our own process, which will then issue # an XSetInputFocus on itself. w = self.get_window() now = x11_get_server_time(w) send_wm_take_focus(w, now)
def do_map(self): Gtk.Window.do_map(self) # We are being mapped, so we can focus ourselves. # Check for the property, just in case this is the second time we are # being mapped -- otherwise we might miss the special call to # reset_x_focus in do_focus_in_event: if not self.get_property("has-toplevel-focus"): # Take initial focus upon being mapped. Technically it is illegal # (ICCCM violating) to use CurrentTime in a WM_TAKE_FOCUS message, # but GTK doesn't happen to care, and this guarantees that we # *will* get the focus, and thus a real FocusIn event. send_wm_take_focus(self.get_window(), CurrentTime)
def do_map(self, *args): gtk.Window.do_map(self, *args) # We are being mapped, so we can focus ourselves. # Check for the property, just in case this is the second time we are # being mapped -- otherwise we might miss the special call to # reset_x_focus in do_focus_in_event: if not self.get_property("has-toplevel-focus"): # Take initial focus upon being mapped. Technically it is illegal # (ICCCM violating) to use CurrentTime in a WM_TAKE_FOCUS message, # but GTK doesn't happen to care, and this guarantees that we # *will* get the focus, and thus a real FocusIn event. send_wm_take_focus(self.window, CurrentTime)
def test_send_wm_take_focus(self): self.evs = [] win = self.window() l.add_event_receiver(win, self) gtk.gdk.flush() send_wm.send_wm_take_focus(win, 1234) gtk.main() assert len(self.evs) == 1 event = self.evs[0] assert event is not None assert event.window is win assert event.message_type == "WM_PROTOCOLS" assert event.format == 32 assert event.data == (l.get_xatom("WM_TAKE_FOCUS"), 1234, 0, 0, 0)