def on_ready(self, app): firsttimefile = config.get('help.first_time_file', os.path.expanduser('~/.samuraix/firsttime') ) if os.path.exists(firsttimefile) or config.get('help.no_first_time', False): return else: filedir = os.path.dirname(firsttimefile) if not os.path.exists(filedir): os.makedirs(filedir) with open(firsttimefile, 'w') as f: f.write('hello') self.show_help()
def add_client(self, client): """ add a client. if the window as a _NET_WM_DESKTOP example, respect it, otherwise place it on the active desktop. """ desktops = [self.active_desktop] reply = client.window.get_property('_NET_WM_DESKTOP', 'CARDINAL').reply() if reply.exists: # has a property like this desktop_idx = reply.value[0] if desktop_idx < len(self.desktops): # we have this desktop! log.debug('Placing %s on desktop %d' % (client, desktop_idx)) desktops = [self.desktops[desktop_idx]] elif desktop_idx == 0xffffffff: desktops = self.desktops if self.screen.conn.atoms['_NET_WM_STATE_STICKY'] in client.state: desktops = self.desktops for desktop in desktops: # so, either the window doesn't have this property # or we don't have this desktop index, so place it on the active desktop desktop.add_client(client) # should it be focused automatically? but don't do if it isn't # the active desktop if (desktop.active and config.get('desktops.autofocus', True)): self.screen.focus(client)
def redraw(self): log.debug('Redrawing, active=%s, obsolete=%s' % (self._active, self._obsolete)) extents = cairo.cairo_text_extents_t() window_title = self.client.get_window_title().encode('utf-8') # <- TODO: is that too expensive? if self.client.is_focused(): bg_color = hex_to_cairo_color(config['cairodeco.color']) fg_color = hex_to_cairo_color(config['cairodeco.title.color']) else: bg_color = hex_to_cairo_color(config.get('cairodeco.inactive_color', config['cairodeco.color'])) fg_color = hex_to_cairo_color(config.get('cairodeco.title.inactive_color', config['cairodeco.title.color'])) cairo.cairo_set_source_rgba(self.cr, bg_color[0], bg_color[1], bg_color[2], 1) cairo.cairo_set_operator(self.cr, cairo.CAIRO_OPERATOR_SOURCE) cairo.cairo_paint(self.cr) cairo.cairo_set_operator(self.cr, cairo.CAIRO_OPERATOR_OVER) cairo.cairo_set_source_rgba(self.cr, fg_color[0], fg_color[1], fg_color[2], 1) cairo.cairo_show_text(self.cr, window_title) cairo.cairo_text_extents(self.cr, window_title, extents) width = self.client.geom.width x = 0 if config['cairodeco.title.position'] == 'left': x = 0 elif config['cairodeco.title.position'] == 'right': x = width - extents.x_advance elif config['cairodeco.title.position'] == 'center': x = (width - extents.x_advance) / 2 cairo.cairo_move_to(self.cr, x, config['cairodeco.height'] - (config['cairodeco.height'] - extents.height) / 2.0) self.client.conn.flush()
def on_load_config(self, config): #self.names = config.get('desktops.names', ['one desktop']) self.config = config.get('desktops.desktops', ())
def create_actor_window(self): screen = self.screen client = self.client colormap = client.window.get_attributes().reply().colormap config = self.plugin.config geom = self.client.window.get_geometry().reply() # dont know how to get this from client.window so setting it to 0 client.window.configure(border_width=0) window_border = 0 border = 2 title_height = config.get('decorator.title.height', 20) client.actor = xproto.Window.create(self.plugin.app.conn, screen.root, screen.info.root_depth, screen.info.root_visual, geom.x, geom.y, # dont forget the borders of client.border in this calculation geom.width + (2*border) + (2*window_border), geom.height + title_height + (2*border) + (2*window_border), override_redirect=True, back_pixel=screen.info.white_pixel, colormap=colormap, # does this help flickering probs? im not sure... backing_store=xproto.BackingStore.WhenMapped, event_mask= xproto.EventMask.Exposure | xproto.EventMask.StructureNotify | # Child.StructureNotify and Parent.SubstructureNotify # seem to block each other. That's not what we want. # I commented this out, and it seems to work. #xproto.EventMask.SubstructureNotify | xproto.EventMask.SubstructureRedirect | xproto.EventMask.ButtonPress, ) client.window.add_to_save_set() client.window.reparent(client.actor) log.debug('created client actor client=%s actor=%s', client, client.actor) # check if we are on the active desktop. unban/ban # the client to get a valid WM_STATE and map the # actor window if needed. current = client.screen.info.ewmh_get_current_desktop() desktop = client.window.ewmh_get_desktop() if (current is None or current == desktop): log.debug('Unbanning %s because it is on the active desktop.' % client) client.unban() else: log.debug('Banning %s because it is not on an active desktop (active=%s, client\'s=%s)' % (client, current, desktop)) client.ban(False, False) self.ui = ui.TopLevelContainer( client.actor, screen.info.get_root_visual_type(), style=config.get('decorator.actor.style', self.default_actor_style), layouter=ui.VerticalLayouter, ) window_title = self.client.get_window_title().encode('utf-8') title_sizer = ui.Container( style={'height': title_height}, layouter=ui.HorizontalLayouter, ) self.ui.add_child(title_sizer) def make_func(bindings): parsed_bindings = {} for k, v in bindings.iteritems(): parsed_bindings[parse_buttonstroke(k)] = v def r(e): try: func = parsed_bindings[(e.state, e.detail)] except KeyError: return if type(func) == str: self.plugin.app.plugins['actions'].emit(func, { 'screen': screen, 'x': e.event_x, 'y': e.event_y, 'client': self.client, }) else: func() return r for button in config.get('decorator.buttons.leftside', []): but = ui.PangoLabel( text=button.get('text'), style=button.get('style'), on_button_press=make_func(button.get('bindings')), ) title_sizer.add_child(but) self.title = ui.PangoLabel( text=window_title, style=config.get('decorator.title.style', self.default_title_style), on_button_press=make_func(config.get('decorator.title.bindings')), ) title_sizer.add_child(self.title) for button in config.get('decorator.buttons.rightside', []): but = ui.Label( text=button.get('text'), style=button.get('style'), on_button_press=make_func(button.get('bindings')), ) title_sizer.add_child(but) style = config.get('decorator.clientwindow.style', self.default_clientwindow_style).copy() style['width'] = geom.width style['height'] = geom.height self.clientwin = ClientWindow( client.window, style=style, ) self.ui.add_child(self.clientwin) #self.ui.layout() #log.debug('after layout size is %s %s', self.ui.width, self.ui.height) #self.ui.render() client.push_handlers( on_focus=self.on_focus, #on_updated_geom=self.on_updated_geom, on_blur=self.on_blur, #on_handle_net_wm_state=self.on_handle_net_wm_state, ) client.window.push_handlers( on_property_notify=self.on_property_notify, on_configure_notify=self.window_on_configure_notify, #on_unmap_notify=self.on_unmap_notify, #on_map_notify=self.on_map_notify, ) # TODO: dirty. something's wrong with substructure and structure notify. #client.screen.root.push_handlers( # #on_configure_notify=self.screen_on_configure_notify, #) client.actor.push_handlers( on_configure_request=self.actor_on_configure_request, ) self.ui.fit() self.clientwin.style['width'] = None self.clientwin.style['height'] = None
def on_load_config(self, config): for stroke, action in config.get('clientbuttons.bindings', {}).iteritems(): buttonstroke = parse_buttonstroke(stroke) self.bindings[buttonstroke] = action
def on_load_config(self, config): self.focus_method = self.styles[config.get('focus.style', 'click')]
def on_load_config(self, config): for stroke, action in config.get('cairodeco.bindings', {}).iteritems(): self.bindings[parse_buttonstroke(stroke)] = action
def show_help(self, *ignore): url = config.get('help.url', 'http://samurai-x.org/wiki/UserManual') log.warning('showing da help') webbrowser.open(url)